我有一个列表,其中包含我要清理的重复Student
个对象。如果列表中的对象具有相同的名称和ID,则应将其删除。
有人可以帮助下面的Comparator实现吗?
public class RemoveDuplicate {
public static void main(String[] args) {
final ArrayList students = new ArrayList();
students.add(new Student("Student1", "1000", "1"));
students.add(new Student("Student2", "1001", "2"));
students.add(new Student("Student3", "1002", "3"));
students.add(new Student("Student4", "1001", "4"));
students.add(new Student("Student1", "1003", "45"));
students.add(new Student("Student1", "1000", "46"));
students.add(new Student("Student4", "1001", "47"));
Set set = new TreeSet(new StudentsComparator());
set.addAll(students);
final ArrayList newList = new ArrayList(set);
System.out.println(newList);
}
}
class StudentsComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
System.out.println(s1 + "," + s2);
if (s1.getId().equalsIgnoreCase(s2.getId())) {
if (s1.getNum().equalsIgnoreCase(s2.getNum())) {
System.out.println("return0");
return 0;
}
}
return 1;
}
}
实际输出:
Name=Student1 Id=1000 Num=1,
Name=Student2 Id=1001 Num=2,
Name=Student3 Id=1002 Num=3,
Name=Student4 Id=1001 Num=4,
Name=Student1 Id=1003 Num=45,
Name=Student1 Id=1000 Num=46,
Name=Student4 Id=1001 Num=47]
预期产出:
Name=Student1 Id=1000 Num=1,
Name=Student2 Id=1001 Num=2,
Name=Student3 Id=1002 Num=3,
Name=Student4 Id=1001 Num=4,
Name=Student1 Id=1003 Num=45]
谢谢
答案 0 :(得分:0)
您的Comparator
实施不正确,因为当前对象始终等于或大于比较对象(您永远不会返回负值)。
所以对称规则不受尊重:
实现者必须确保sgn(x.compareTo(y))== -sgn(y.compareTo(x))表示所有x和y。
无论如何,要删除重复项,TreeSet
如果您不想对它们进行排序则不合适。
而不是覆盖equals()
课程中的hashCode()
和Student
,并在ArrayList
中添加您的元素(最初位于LinkedHashSet
)以保留实际订单。
final List<Student> students = new ArrayList<>();
students.add(new Student("Student1", "1000", "1"));
students.add(new Student("Student2", "1001", "2"));
...
LinkedHashSet<Student> set = new LinkedHashSet<>(students);
答案 1 :(得分:0)
你的Comparator违反了比较合同:
比较其订单的两个参数。当第一个参数小于,等于或大于第二个参数时,返回负整数,零或正整数。
此外,TreeSet
中的添加需要log(n)
(这不是很糟糕,特别是对于那些大型集合而言),如果您可以覆盖equals
和{{1}这通常是一个更好的选择。
但是,如果您希望自动生成自定义比较器,或者无法/想要覆盖hashcode
和equals
,则可以使用hashcode
和comparing
函数提供了java thenComparing
。
Comparator
此比较器功能通常更易于使用,并且可能更不容易出错。您可以照常在Comparator<Student> studentComparator = Comparator
.comparing((Student student) -> student.getId().toLowerCase())
.thenComparing((Student student) -> student.getNum().toLowerCase());
中使用它。
然而,这个比较器不是空的安全,你需要传递TreeSet
作为第二个参数来允许比较空值。并且在致电Comparator.nullsFirst(Comparator.naturalOrder())
之前检查字符串。
您可以使用一些辅助方法(或者创建一个定义类似的自定义比较器):
toLowerCase()
例如,如果public static String handleCase(String str) {
return str != null ? str.toLowerCase() : null;
}
public static <T extends Comparable<? super T>> Comparator<T> nullComparator() {
return Comparator.nullsFirst(Comparator.naturalOrder());
}
是可以为空的属性,则可以使用:
num
最后,如果您想从“任何地方”访问此比较器,您可以将定义包装在比较器中,作为Comparator<Student> studentComparator = Comparator
.comparing((Student student) -> handleCase(student.getId()))
.thenComparing((Student student) -> handleCase(student.getNum()), nullComparator());
字段,或final
作为单例,或者作为{自定义比较器的辅助类中的{1}}字段。
答案 2 :(得分:0)
以下是您特定问题的运行代码。
学生班级
public class Student {
private String name;
private String id;
private String num;
public Student(String name, String id, String num) {
super();
this.name = name;
this.id = id;
this.num = num;
}
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;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + ", num=" + num + "]";
}
主要课程
public class RemoveDuplicate {
public static void main(String[] args) {
final ArrayList students = new ArrayList();
students.add(new Student("Student1", "1000", "1"));
students.add(new Student("Student2", "1001", "2"));
students.add(new Student("Student3", "1002", "3"));
students.add(new Student("Student4", "1001", "4"));
students.add(new Student("Student1", "1003", "45"));
students.add(new Student("Student1", "1000", "46"));
students.add(new Student("Student4", "1001", "47"));
Set set = new TreeSet(new StudentsComparator());
set.addAll(students);
final ArrayList newList = new ArrayList(set);
System.out.println(newList);
}
}
class StudentsComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
if (s1.getId().compareTo(s2.getId()) == 0)
return s1.getName().compareTo(s2.getName());
else
return s1.getId().compareTo(s2.getId());
}
}