【问题标题】:Sorting objects within a Set by a String value that all objects contain按所有对象包含的字符串值对 Set 中的对象进行排序
【发布时间】:2010-11-09 09:55:24
【问题描述】:

好的,这是一个棘手的问题。我有一个集合列表。我想按顺序对 Sets 中的对象进行排序。

将每个集合想象成代表学校中的一个班级。每个集合都包含人员对象。一个人对象持有一个字符串值作为名称。我想在循环并写出之前按名称排列 Set 中的 Persons。

有没有办法使用Collections.sort(); 或类似的东西来实现这一点?

for (Set<Person> s : listOfAllChildren) {       
      for (Person p : s) {
        if(p.getClass().equalsIgnoreCase("Jones")){
          System.out.println(p.getName());
          }
         else if...//carry on through other classes 
        }                              
      }        

我知道一个班有 2 个以上的孩子可能有相同的名字,但请忽略这个

【问题讨论】:

  • if 在第 2 行是不必要的。
  • 我希望,第 3 行中的 p.getClass() 只是一个错字,您没有为每个个人或家庭设置一个单独的类 ;-)
  • @Andreas_D:Person 只有一个类,但是从这个类创建了很多人对象。这是一个问题吗? getClass 方法返回该班级的教师姓名。Person 对象由电子表格数据动态生成。
  • 我更改了标题以反映它是您要排序的集合这一事实。如果您不同意,请回滚。
  • getClass() 不返回字符串(教师姓名),而是返回 Class 对象。您可以将其与字符串进行比较,但结果将始终为false。并且“重新定义”getClass() 以返回 String 的类将无法编译。

标签: java sorting object set


【解决方案1】:

Set 没有排序的概念,因为它是一个集合。

有一个由TreeSet 类实现的SortedSet 接口,您可以使用它。只需向构造函数提供适当的Comparator,或者让您的Person 类实现Comparable

【讨论】:

    【解决方案2】:

    使用 Java 8,您可以对人员的 Set 进行排序,并生成人员的 List,其排序如下。

    List<Person> personList = personSet.stream().sorted((e1, e2) -> 
    e1.getName().compareTo(e2.getName())).collect(Collectors.toList());
    

    【讨论】:

    • 这是 IMO 的最佳答案。
    • 执行相同代码的方法参考方法: List personList = personSet.stream().sorted(Comparator.comparing(Person::getName)).collect(Collectors.toList()) ;
    【解决方案3】:

    您必须为您的可排序对象实现ComparablePerson 等)。

    然后:

    1. 将集合转换为列表(一些信息here),因为您无法对Set 进行排序
    2. 使用Collections.sort

    1. 转换为SortedSet(如TreeSet
    2. 使用Comparator 进行自定义订购

    例子:

    import java.util.*;
    
    class Person implements Comparable<Person> {
        private String firstName, lastName;
    
        public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName;}
        public String getFirstName() {return firstName;}
        public String getLastName() {return lastName;}
        public String getName() {return firstName + " " + lastName;}
    
        public int compareTo(Person p) {
            return lastName.compareTo(p.lastName);
        }
    }
    
    class FirstNameComparator implements Comparator<Person> {
        public int compare(Person p1, Person p2){
                return p1.getFirstName().compareTo(p2.getFirstName());
        }
    }
    
    class Test {
      public static void log(String s) {
            System.out.println(s);
        }
    
      public static void main(String[] args) {
            Set<Person> people = new HashSet<Person>();
            people.add(new Person("Bob", "Jones"));
            people.add(new Person("Alice", "Yetti"));
    
            log("Sorted list:");
            List<Person> peopleList = new LinkedList<Person>();
            peopleList.addAll(people);
            Collections.<Person>sort(peopleList);
            for (Person p : peopleList) {
                log(p.getName());
            }
    
            log("TreeSet:");
            TreeSet<Person> treeSet = new TreeSet<Person>();
            treeSet.addAll(people);
            for (Person p : treeSet) {
                log(p.getName());
            }
    
            log("TreeSet (custom sort):");
            TreeSet<Person> treeSet2 = new TreeSet<Person>(new FirstNameComparator());
            treeSet2.addAll(people);
            for (Person p : treeSet2) {
                log(p.getName());
            }
          }
    };
    

    【讨论】:

    • +1 搜索了整个网络以找到如何针对 String 实现 compareTo。谢谢! :P
    【解决方案4】:

    您可以考虑使用 TreeSet 来存储对象。并且在排序时为您的 Person 对象创建带有自定义比较器的新 TreeSet。我不建议使用 Collection.sort,因为 AFAIR 它只能对列表进行排序。

    【讨论】:

      【解决方案5】:

      您可以让您的 Person 类实现 Comparable 接口,如 here 所示,然后对它们进行相应的排序。

      【讨论】:

        【解决方案6】:

        您可能想看看使用SortedSet,例如TreeSet。这允许您提供一个Comparator,在您的情况下可以比较Person 的名称。

        【讨论】:

          【解决方案7】:

          是的!这你绝对可以使用 Collection.sort()。但是您将需要使用排序集(如 TreeSet)。或者,您也可以先将 Set 中的所有元素插入到列表中。

          然后,您的 Person 类需要实现 Comparable,因为 Collections.sort() 会在尝试决定放置它们的顺序时调用此接口。所以它可以很简单,比如:

          public class Person implements Comparable<Person> {
            ...
            @Override
            public int compareTo(Person p) {
              return this.name.compareTo(p.name);
            }
          }
          

          如果使用 TreeSet,它应该已经排序。否则,如果使用列表,只需在每个列表上调用 Collections.sort(List l)。

          【讨论】:

          • +1 因为我犯了同样的错误,现在退出了。您更新了答案,但仍在战斗;)。我总是将SetList 混淆。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-04
          • 2012-12-24
          • 2019-08-02
          • 1970-01-01
          • 2020-12-08
          • 2020-05-24
          • 2021-06-27
          相关资源
          最近更新 更多