简体   繁体   English

TreeSet没有按升序排列值

[英]TreeSet not arranging value in ascending order

I am trying to create a TreeSet to sort the strings which are inserted to be in an ascending order.我正在尝试创建一个 TreeSet 来对插入的字符串进行升序排序。 I am using below code for entering values in TreeSet.我正在使用下面的代码在 TreeSet 中输入值。

TreeSet<String> ts = new TreeSet<String>();

ts.add("@Test0");
ts.add("@Test1");
ts.add("@Test2");
ts.add("@Test3");
ts.add("@Test10");
ts.add("@Test4");

System.out.println("Tree set :: "+ts);

Output: Output:

Tree set:: [@Test0, @Test1, @Test10, @Test2, @Test3, @Test4]树集:: [@Test0, @Test1, @Test10, @Test2, @Test3, @Test4]

You've used the no-args TreeSet constructor.您已经使用了无参数 TreeSet 构造函数。 This means TreeSet will order its elements based on natural order .这意味着 TreeSet 将根据自然顺序对其元素进行排序。 It's the way the objects compare themselves: It means the things you add must be of a type that implements Comparable<Self> .这是对象比较自己的方式:这意味着您添加的东西必须是实现Comparable<Self>的类型。 String does that: The String class is defined to implement Comparable<String> . String 这样做: String class 被定义为实现Comparable<String> However, the way strings compare themselves is lexicographically.但是,字符串比较自身的方式是按字典顺序进行的。 10 comes before 2 for the same reason that aa comes before b. 10 在 2 之前,原因与 aa 在 b 之前相同。

You have two routes available to fix this:您有两条路线可以解决此问题:

  1. Don't put strings in there but some other object that implements Comparable and does it right.不要把字符串放在那里,但其他一些 object 实现了 Comparable 并且做得对。 Perhaps a class Thingie {String name; int idx;}也许是class Thingie {String name; int idx;} class Thingie {String name; int idx;} . class Thingie {String name; int idx;}

  2. Pass a Comparator as first and only argument to your TreeSet class.Comparator器作为第一个也是唯一的参数传递给 TreeSet class。 Write code that determines that @Test10 comes before @Test2 .编写确定@Test10 @Test2之前的代码。 Then, TreeSet uses this comparator to determine ordering and won't use the one built into strings.然后,TreeSet 使用此比较器来确定排序,并且不会使用内置在字符串中的比较器。

@Test10 comes before @Test2 because 1 comes before 2 . @Test10出现在@Test2之前,因为1出现在2之前。 That's how the default ordering of String works ( String implements the interface Comparable to do this sorting).这就是String的默认排序的工作方式( String实现了Comparable接口来进行这种排序)。

To solve your issue you need to provide a custom Comparator to the TreeSet , and do the comparison by parsing the integer within the string:要解决您的问题,您需要为TreeSet提供自定义Comparator ,并通过解析字符串中的 integer 进行比较:

TreeSet<String> ts = new TreeSet<String>(new Comparator<String>() {

    @Override
    public int compare(String s1, String s2) {
        return Integer.parseInt(s1.substring(5)) - Integer.parseInt(s2.substring(5)); 
    }
});

The comparator can be constructed using the static convenience method:可以使用 static 便捷方法构建比较器:

TreeSet<String> ts = new TreeSet<>(Comparator.comparing(s -> Integer.parseInt(s.substring(5))));

Specify the Comparator to sort on the number part only.指定 Comparator 仅对数字部分进行排序。 This removes all but the number portion, converts that to an integer and sorts on that.这将删除除数字部分之外的所有部分,将其转换为 integer 并对其进行排序。

TreeSet<String> ts = new TreeSet<String>(Comparator.comparing(
        s -> Integer.valueOf(s.replace("@Test", ""))));

ts.add("@Test0");
ts.add("@Test1");
ts.add("@Test2");
ts.add("@Test3");
ts.add("@Test10");
ts.add("@Test4");

System.out.println(ts);

prints印刷

[@Test0, @Test1, @Test2, @Test3, @Test4, @Test10]

This works for the shown example.这适用于所示示例。 You may need to modify it somewhat for more varied data.您可能需要对其进行一些修改以获取更多不同的数据。 But it demonstrates the idea.但它证明了这个想法。

As @Jems noted in the comment, strings are sorted lexichographically, so "@Test10" will come before "@Test2".正如@Jems 在评论中指出的那样,字符串按字典顺序排序,因此“@Test10”将位于“@Test2”之前。 If could however, supply a custom Comparator to define the order you need.但是,如果可以,请提供自定义Comparator器来定义您需要的顺序。 Eg, if you know all the strings will have the form of "@Test" followed by a number, you could extract this number and sort accordingly:例如,如果您知道所有字符串的形式都是“@Test”后跟一个数字,那么您可以提取该数字并进行相应的排序:

TreeSet<String> ts = 
    new TreeSet<>(Comparator.comparingInt(s -> Integer.parseInt(s.substring(5))));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM