3

我有一个像这样的java类

public class A {

    private String field1;
    private String field2;

    // getters, setters but no equals and hashcode
}

和这个类的对象列表,我想从这个列表中删除所有具有相同field1或相同field2的重复元素,所以我有2个比较器

public class Comparator1 implements Comparator<A> {
    public int compare(A o1, A o2) {

        return o1.getField1().compareToIgnoreCase( o2.getField1() );
    }
}

public class Comparator2 implements Comparator<A> {
    public int compare(A o1, A o2) {

        return o1.getField2().compareToIgnoreCase(o2.getField2());
    }
}

所以为了完成任务,我使用 treeset 之类的

TreeSet<A> ts1 = new TreeSet<A>(new Comparator1())
ts1.addAll(list)

TreeSet<A> ts2 = new TreeSet<A>(new Comparator2())
ts2.addAll(ts1)

list.clear()
list.addAll(ts2)

但是我怎样才能只使用一个比较器和一个树集来做同样的事情呢?

谢谢您的帮助

更新:

感谢所有人的答案,但在阅读它们之后,我不知道这是否是解决实际问题的正确方法。

在我的真实案例中,field1 就像一个电话号码,而 field2 就像一个名字。所以我不想多次拨打同一个电话号码(这是第一个删除重复的树集),我不想多次拨打相同的名字(第二个删除重复的树集)

您可以修改课程,但我想知道这种方法是否可以解决真正的问题。

如果这种方法是正确的,从你的问题来看,我看到不修改类是不可能只使用一个比较器

谢谢

4

6 回答 6

2

您不能使用一个比较器同时按两个标准进行排序,因此在您的情况下,没有比两个 TreeSet 更好的真正方法。当然,您可以将它们包装在一个数据结构中。

(或者,您可以使用两个 HashMap,每个都有一个字符串作为键 - 这平均会更快,但编程更复杂。)

于 2011-04-09T00:29:33.367 回答
1

你不能,而且我不清楚你试图做的事情是明确定义的。

您是否知道您当前的方法既取决于添加元素的顺序,也取决于您是否首先检查 field1 或 field2 是否有重复项?想象一下,您有这些 A 类对象:

A ab = new A("a", "b");
A cb = new A("c", "b");
A cd = new A("c", "d");

首先检查 field1 会给出结果[ab][ab, cd],具体取决于添加的顺序。

首先检查 field2 会给出结果[cb][ab, cd],具体取决于添加的顺序。

这是非常奇怪的行为。这是你想要的吗?在一般情况下,我认为不可能用单个 TreeSet 和 Comparator 来重现它。

于 2011-04-09T01:06:44.907 回答
0
public static <A extends Comparable<?>>  TreeSet<A> getTreeSet(Collection<A> list){
    TreeSet<A> result = new TreeSet<A>();
    HashSet<A> unique = new HashSet<A>();
    unique.addAll(list);
    result.addAll(unique);
    return result;
}

将项目添加到 hashset 以使其唯一,然后将它们放入 TreeSet 进行排序的通用函数。您可以将其用于:TreeSet<A> ts1 = getTreeSet(list);

这种方法适用于固定列表。

@BalusC 不,这是假设

public class A implements Comparable<A> {

    private String field1;
    private String field2;

    @Override
    public int compareTo(A o) {
        // No null checks, because it's illegal anyways.
        int tmp = 0;
        if ((tmp = field1.compareToIgnoreCase(o.field1)) != 0)
            return tmp;
        if ((tmp = field2.compareToIgnoreCase(o.field2)) != 0)
            return tmp;
        return tmp;
    }
    // getters, setters but no equals and hashcode
}
于 2011-04-09T00:44:12.340 回答
0

如果您打算进行两级排序(第一:电话号码和第二:姓名),那么您可以使用以下代码,其中将针对两个字段(字段 1 和字段 2)进行重复检查。由于我们已经对这两个字段使用了compareTo,因此不需要使用equalshashcode。但是使用hashcodeequals总是好的做法。

public class A implements Comparable<A> {

private String field1;
private String field2;

public A(String number, String name) {
    this.field1 = number;
    this.field2 = name;
}

// First level sorting will be done by field1. 
// If field1 is equal then second level sorting will be done on field2
@Override
public int compareTo(A o) {
    int compareTo = field1.compareTo(o.getNumber());
    if(compareTo==0){
        return field2.compareTo(o.getName());
    }
    return compareTo;
}

public String getNumber() {
    return field1;
}

public String getName() {
    return field2;
}

}

于 2014-05-27T08:00:00.480 回答
0
public class RemoveDuplicate {

public static void main(String[] args) {

    final ArrayList<Student> students = new ArrayList<Student>();

    Set<Student> set = new TreeSet<Student>();
    Student[] starr = new Student[6];
    starr[0] = new Student("Student1", "1005");
    starr[1] = new Student("Student2", "1004");
    starr[2] = new Student("Student3", "1003");
    starr[3] = new Student("Student6", "1002");
    starr[4] = new Student("Student5", "1001");
    starr[5] = new Student("Student6", "1000");

    Arrays.sort(starr, Student.StudentIdComparator);
    for (Student s : starr) {
        students.add(s);
    }

    System.out.println(students);
    set.addAll(students);

    System.out.println("\n***** After removing duplicates *******\n");

    final ArrayList<Student> newList = new ArrayList<Student>(set);

    /** Printing original list **/
    System.out.println(newList);
}}
于 2018-03-16T06:06:47.937 回答
0
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.Comparator;
 import java.util.List;

 public class RemoveDuplicate {

public static void main(String[] args) {
    Set<Student> set = new TreeSet<Student>();
    List<Student> students = Arrays.asList(new Student("Student1", "1005"), new Student("Student2", "1004"),
            new Student("Student3", "1003"), new Student("Student6", "1002"), new Student("Student5", "1001"),
            new Student("Student6", "1000"));

    // Sorting Using Lambda

    students.sort(new Comparator<Student>() {

        @Override
        public int compare(Student s1, Student s2) {

            return s1.getId().compareTo(s2.getId());
        }

    });

    System.out.println(students);
    set.addAll(students);

    System.out.println("\n***** After removing duplicates *******\n");

    final ArrayList<Student> newList = new ArrayList<Student>(set);

    /** Printing original list **/
    System.out.println(newList);
}

  }

 class Student implements Comparable<Student> {
private String name;
private String id;

public Student(String name, String id) {
    this.name = name;
    this.id = id;
}

public String getName() {
    return name;
}

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

public String getId() {
    return id;
}

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

@Override
public String toString() {
    return "\n" + "Name=" + name + "   Id=" + id;
}

@Override
public int compareTo(Student o1) {
    if (o1.getName().equalsIgnoreCase(this.name)) {
        return 0;
    }
    return 1;
    }

// public static Comparator<Student> StudentIdComparator = (Student
// s1,Student s2) -> s1.getId().compareTo(s2.getId());
   }
于 2018-03-16T06:10:00.137 回答