带有 Comparator<?> 参数的 TreeSet 构造函数

TreeSet constructor with Comparator<?> parameter

Java’s documentation for its class TreeSet 中,其中一个构造函数显示为具有以下 header:

TreeSet(Comparator<? super E> c)

谁能帮忙解释一下为什么 TreeSet 有一个构造函数,它以比较器 object 作为参数?我不知道为什么这样做。

TreeSet 中的元素保持排序。

如果您使用没有比较器的构造函数,元素 class 的自然顺序(由 Comparable 的实现定义)将用于对 TreeSet 的元素进行排序。

如果您想要不同的顺序,请在构造函数中提供一个比较器。

用于按照用户定义的规则对Set中的元素进行排序。

javadoc

public TreeSet(Comparator comparator)

Constructs a new, empty tree set, sorted according to the specified comparator.

All elements inserted into the set must be mutually comparable by the specified comparator: comparator.compare(e1, e2) must not throw a ClassCastException for any elements e1 and e2 in the set.

If the user attempts to add an element to the set that violates this constraint, the add call will throw a ClassCastException.

Parameters:

comparator - the comparator that will be used to order this set. If null, the natural ordering of the elements will be used.

有关自然对象排序的更多信息,请参见here

Comparator interface is used to order the objects of user-defined class.

它提供了多种排序顺序,即您可以根据任何数据成员对元素进行排序。例如,它可能在 rollno、姓名、年龄或其他任何内容上。

通过在 TreeSet(Comparator<? super E> c) 中传递一个比较器,这意味着您可以根据需要的参数对 TreeSet 进行排序。

We can say that by passing a Comparator in TreeSet we can order the TreeSet as we desire and not use the natural ordering used by TreeSet.

假设您有 TreeSet<User> 并且您有一个用户 class,其中包含字段 id

现在,如果您想根据用户 ID 对 TreeSet 进行排序,您可以在 TreeSet 中传递一个 Comparator 对象以获得所需的顺序。

此构造函数允许您定义将 T 插入到 Set 后面的树中时使用的 Comparator

Comparator<String> comp = (String o1, String o2) -> (o1.compareTo(o2));
Set<String> ts = new TreeSet<>(comp);

A​​ TreeSet 是一个 binary search tree,它基于给定两个元素 ab[=21 的概念=], 要么 a 是 "smaller than" b, 要么不是。但是,如果您定义自己的 class,TreeSet 不知道如何确定那个 class 的给定对象是否是 "smaller than" 另一个对象,因为它不能了解您对对象内容的预期解释。因此,您可以创建一个可以代表 TreeSet.

进行比较的 Comparator
The following code shows how to use TreeSet.TreeSet(Comparator <? super E > comparator) constructor.
/**
 *Output: 
 F E D C B A 
  */

import java.util.Comparator;
import java.util.TreeSet;

class MyComparator implements Comparator<String> {
  public int compare(String a, String b) {
    String aStr, bStr;

    aStr = a;
    bStr = b;

    return bStr.compareTo(aStr);
  }
  // No need to override equals.
}

public class MainClass {
  public static void main(String args[]) {
    TreeSet<String> ts = new TreeSet<String>(new MyComparator());

    ts.add("C");
    ts.add("A");
    ts.add("B");
    ts.add("E");
    ts.add("F");
    ts.add("D");

    for (String element : ts)
      System.out.print(element + " ");

    System.out.println();
  }
}

Treeset class 具有以下构造函数,因此 Treeset 按照比较器描述的顺序使用 存储元素 c.Below 是一个示例来说明这一点。

    **Constructor :-**
    TreeSet(Comparator<? super E> c)
class Employeee {
            public Employeee(int id, String name) {
                super();
                this.id = id;
                this.name = name;
            }

            public int getId() {
                return id;
            }

            public void setId(int id) {
                this.id = id;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            private int id;
            private String name;
        }

        class namecomp implements Comparator<Employeee> {
            public int compare(Employeee paramT1, Employeee paramT2) {
                if (paramT1.getName().compareTo(paramT2.getName()) > 0)
                    return -1;
                else if (paramT1.getName().compareTo(paramT2.getName()) < 0)
                    return 1;
                else
                    return 0;
            }
        }

        public class TreeSetImpl {
            public static void main(String[] args) {
                SortedSet<Employeee> treeSet = new TreeSet<Employeee>(new namecomp());
                Employeee e1 = new Employeee(1, "Iftekhar");
                Employeee e2 = new Employeee(2, "Khan");
                Employeee e3 = new Employeee(3, "Apple");
                treeSet.add(e1);
                treeSet.add(e2);
                treeSet.add(e3);
                Iterator<Employeee> it = treeSet.iterator();
                while (it.hasNext()) {
                    System.out.println(it.next().getId());
                }
            }
        }

在这里,如果您看到 namecomp 正在实现 Comparator 接口,从而根据 Name 字段按降序对 Employeee class 的元素进行排序。 现在 Treeset 正在实现 namecomp 比较器,以在 Name 字段的基础上按降序存储元素。 输出 2个 1个 3

希望这能回答问题。

具有默认构造函数的 TreeSet 将按自然升序对元素进行排序,但如果您希望根据您的要求进行一些自定义排序,那么您应该使用 Comparator 接口。 当量 这是您的默认 class 员工,然后您想根据薪水对这个 class 进行排序。

public class Employee {

private int Id;

private String name;

private int salary;

public Employee(int id, String name, int salary) {

    super();
    Id = id;
    this.name = name;
    this.salary = salary;
}
public int getId() {

    return Id;
}
public void setId(int id) {

    Id = id;
}
public String getName() {

    return name;
}
public void setName(String name) {

    this.name = name;
}
public int getSalary() {

    return salary;
}
public void setSalary(int salary) {

    this.salary = salary;
}

public String toString() {

    return "ID : "+Id +" Name : "+name+" Salary : "+salary+"\n";
}
}

这里我们通过实现 Comparator 创建了另一个 class。

public class EmpSalaryComparator implements Comparator{

public int compare(Object o1, Object o2) {

    Employee e1=(Employee) o1;
    Employee e2=(Employee) o2;
    return e1.getSalary()-e2.getSalary();
}
}

public class Test1 {

public static void main(String[] args) {

    TreeSet t1=new TreeSet(new EmpSalaryComparator());
    Employee e1=new Employee(1001, "Ram", 1000);
    Employee e2=new Employee(1002, "lucky", 7000);
    Employee e3=new Employee(1003, "sumo", 3000);
    Employee e4=new Employee(1004, "kharvi", 3000);
    Employee e5=new Employee(1005, "priya", 1000);

    t1.add(e1);
    t1.add(e2);
    t1.add(e3);
    t1.add(e4);
    t1.add(e5);
    System.out.println(t1);
}
}

以上所有答案都是正确的,但我想补充一点,自定义比较器除了导致不同的排序外,还会以不同方式过滤值。

由于 Set 的值是单义的,如果自定义 Comparator returns 两个值相同,Set 中只会出现其中一个:

    Set<String> s = new TreeSet<>(new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return s1.trim().compareTo(s2.trim());
        }
    });

    s.add("1");
    s.add(" 1");
    s.add("2 ");
    s.add("2");
    s.add(" 2 ");   

    Arrays.toString(s.toArray()); // [ "1", "2 "]

您还可以将 Lambda 与 Java8

一起使用
Set<T> s = new TreeSet<>((a, b) -> func(a) - func(b));