Java对字符串数组中的Java排序列

时间:2017-04-12 20:41:41

标签: java arrays sorting

我一直在处理this SO question。但是,我的数据安排略有不同。

无需进入 HOW 检索数据,只需说明结果数组如下所示

String[2][]
    [0] = String[4]
    [1] = String[4]

实际数据如下

data = String[2][]
  data[0]
    data[0][0] = "Columbia"
    data[0][1] = "Chile"
    data[0][2] = "Asia"
    data[0][3] = "US"
  data[1]
    data[1][0] = "B216"
    data[1][1] = "B217"
    data[1][2] = "A442"
    data[1][3] = "N665"

我想按字母顺序按数据[0]对整个数组进行排序。然而,我意识到引用的SO问题中提供的解决方案是使用不同的数组格式。

我的预期结果看起来像

data = String[2][]
  data[0]
    data[0][0] = "Asia"
    data[0][1] = "Chile"
    data[0][2] = "Columbia"
    data[0][3] = "US"
  data[1]
    data[1][0] = "A442"
    data[1][1] = "B217"
    data[1][2] = "B216"
    data[1][3] = "N665"

我并不完全确定如何在不迭代每个元素并将它们转移到新数组的情况下获得这些结果。

有什么想法吗?

4 个答案:

答案 0 :(得分:1)

完整代码here

  1. String[]的内部data进行排序。
  2. data添加到ArrayList

    List<String[]> list = new ArrayList<>();
    // Sort the String array and insert it in List
    for (String dataArr[] : data) {
        String s[] = dataArr.clone(); // create new object of String array
        Arrays.sort(s); // Sort newly created String array
        list.add(s);
    }
    
  3. 使用自定义比较器对此列表进行排序。
    3.1请记住,您需要在比较中扫描两个阵列中的整个String[]以找到第一个差异。

    // Sort the list using custom comparator
    Collections.sort(list, new Comparator<String[]>() {
    
        @Override
        public int compare(String[] o1, String[] o2) {
    
            // optional: condition to check for string length equality
            if (o1.length == o2.length) {
                for (int i = 0; i < o1.length; i++) {
                    if (o1[i].equals(o2[i])) { // ** IMP **
                        // allows scanning through entire string array.
                        continue;
                    }
                    // Find the first different strings in both arrays
                    return o1[i].compareTo(o2[i]);
                }
            } else if (o1.length < o2.length) {
                // allow string arrays with lesser elements to appear first
                return -1;
            } else if (o1.length > o2.length) {
                return 1;
            }
    
            // When o1.length == o2.length and all strings are equal
            return 0; // no difference
        }
    
    });
    
  4. 数据(第一行)和排序列表的示例输出 enter image description here

答案 1 :(得分:1)

我可以看到有关如何将多个数组按相同顺序排序的三个选项:

  1. 创建一个索引数组,使用Comparator对其进行排序,该Integer[] indices = new Integer[data[0].length]; for(int i = 0; i < data[0].length; i++) indices[i] = i; Arrays.sort(indices, new Comparator<Integer>() { @Override public int compare(Integer i1, Integer i2) { return data[0][i1].compareTo(data[0][i2]); } }); 引用要根据索引排序的数组,然后根据排序的索引重新排列数组。这是一个示例:

    Integer

    索引数组必须是int而不是Arrays,因为public String[] rearrange(Integer[] indices, String[] input) { String[] output = new String[]; for(int i = 0; i < indices.length; i++) output[i] = input[indices[i]]; return output; } 不允许使用自定义比较器对基元进行排序。然后,您可以通过索引数组重新排列两个数组,执行类似于下面的函数。我无法想到一种方法来做到这一点,而不会弄乱订单并使索引数组无效。

    for(int i = 0; i < data.length; i++)
        data[i] = rearrange(indices, data[i]);
    

    此函数不进行错误检查,以查看输入是否长度相同且不使用流,我相信它可以重写。这只是概念的一个例子。使用它:

    Comparable

    这可能是重新排列数组的内存最少的选项。它的灵感来自this answer question,我认为它与你的重复。

  2. 创建一个对象,该对象包含给定索引处的所有元素并使其成为public class Container implements Comparable<Container> { public final String country; public final String code; public Container(Sting country, String code) { this.country = country; this.code = code; } public int compareTo(Container other) { return this.country.compareTo(other.country); } } 。这是之前引用的accepted answerquestion解决方案。

    objects = new Container[data[0].length];
    for(int i = 0; i < objects.length; i++)
        objects[i] = new Container(data[0][i], data[1][i]);
    Arrays.sort(objects);
    

    您必须将数据转换为这些容器的数组,然后对其进行排序:

    List

    虽然此方法确实需要将数据复制到不同的格式,但实际上它比使用数组数组更强大,因为它将概念上相关的项分组到单个项中。这完全消除了检查数组长度相等的事情以及通常更加面向对象的需要。您甚至可以重写数据输入,只是吐出一个数组或ContainerHashMap<String, String> mapping = new HashMap<>(); for(int i = 0; i < data[0].length; i++) mapping.put(data[0][i], data[1][i]); Arrays.sort(data[0]); String[] outputCodes = new String[data[1].length]; for(int i = 0; i < outputCodes.length; i++) outputCodes[i] = mapping(data[0][i]); data[1] = outputCodes; 个对象而不是2D数组。

  3. 在国家/地区和代码之间创建显式映射,然后根据排序的密钥取消引用值。这就是#1的作用,但它允许您至少对其中一个数组进行就地排序。如果映射是有序映射,则可以直接将其转换为已排序的数组。

    一个。未排序的映射:

    TreeMap<String, String> mapping = new TreeMap<>();
    for(int i = 0; i < data[0].length; i++)
        mapping.put(data[0][i], data[1][i]);
    data[0] = new String[mapping.size()];
    data[1] = new String[mapping.size()];
    int index = 0;
    for(Map.Entry<String, String> entry : mapping.entrySet()) {
        data[0][index] = entry.getKey();
        data[1][index] = entry.getValue();
        index++;
    }
    

    湾排序映射:

        @Stateless
        @DeclareRoles({"role1","role2"})
        @RolesAllowed({"role1","role2"})
        @Path("api-dummy")
        public class DummyApiREST {
    
            @EJB
            private StuffFacade stuffFacade;
    
            @GET
            @Path("get-stuff")
            @Produces({MediaType.APPLICATION_JSON})
            public Response findStuff() {
                Stuff stuff = stuffFacade.getStuff();
                Response.ResponseBuilder builder = Response.status(Response.Status.OK).entity(stuff);
                Utils.setCacheHeader(maxAgeSeconds, builder);
                return builder.build();
            }
       }
    

    这些方法都有缺点,它们只适用于两列数据。如果你有更多,你的值必须成为自定义对象或对象数组或类似的东西。无论哪种方式,这种方法非常笨重,我只是提供它来说明如果你真的想要如何跳过额外的箍。

  4. 可能有其他方法,但正如#3所示,我怀疑它们在速度,记忆力或易读性/可维护性方面与这里显示的三种方式相比不会特别有效。

    另请注意,溪流会让您更轻松地完成我在这里展示的所有内容。

答案 2 :(得分:0)

试试吧。适合我。

        Map<String, String> unsortMap = new HashMap<>();
                unsortMap.put("Columbia", "B216");
                unsortMap.put("Chile", "B217");
                unsortMap.put("Asia", "A442");
                unsortMap.put("US", "N665");

                System.out.println("Original...");
                System.out.println(unsortMap);

                Map<String, String> result = new LinkedHashMap<>();

                //sort by key, a,b,c..., and put it into the "result" map
                unsortMap.entrySet().stream()
                        .sorted(Map.Entry.<String, String>comparingByKey())
                        .forEachOrdered(x -> result.put(x.getKey(), x.getValue()));

                System.out.println("Sorted...");
                System.out.println(result);

答案 3 :(得分:0)

  

解决方案

根据Socowi和Stephen P以及Sorting multiple arrays simultaneously的建议,我想出了以下解决方案

当我将这些数据返回到JSP以填充下拉列表时,我为模型添加了一个类并在数组上迭代,将一个新的模型类实例添加到数组列表

for (int i = 0; i < data[0].length; i++) {
  dataList.add(new LocationModel(data[0][i], data[1][i].trim()));
}

模型类实现Comparable并覆盖compareTo方法

public class LocationModel implements Comparable<LocationModel> {
  ...
  @Override
    public int compareTo(LocationModel other) {
        return this.locName.compareToIgnoreCase(other.getLocName());
    }
}

然后我只是对数组列表进行排序

Collections.sort(dataList);

这解决了我的问题。

感谢大家的帮助