java:Comparator和Treeset删除重复项

时间:2011-04-09 00:08:21

标签: java duplicates comparator treeset

我有一个像这样的java类

public class A {

    private String field1;
    private String field2;

    // getters, setters but no equals and hashcode
}

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

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<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就像一个名字。 所以我不想多次调用相同的电话号码(这是第一个删除重复项的树集),我不想多次调用相同的名称(第二个树集来删除重复项)< / p>

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

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

由于

5 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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重现这一点。

答案 2 :(得分: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
}

答案 3 :(得分:0)

如果您打算进行两个级别的排序(第一个:PhoneNumber和第二个:Name),那么您可以使用以下代码,其中将对两个字段(field1和field2)执行重复检查。由于我们已经对这两个字段使用 compareTo ,因此不需要使用等于哈希码。但使用哈希码等于始终是一种好习惯。

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;
}

}

答案 4 :(得分: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());
   }