比较 Java 中的两个对象列表
Comparing two list of objects in Java
我有两个学生对象列表(listA 和 listB),它们是通过从两个不同的数据库中查询而形成的。我需要迭代一个列表并确保它不存在于另一个列表中。
我使用了下面的比较代码,即覆盖 equals 方法并使用 for 循环进行比较。
假设列表 A 和列表 B 各有 5000 行,您能否建议是否有更好的实现方法?
对比码:
for (Student dataA:listA) {
for (Student dataB:listB) {
if(dataB.equals(dataA))
break;
}
}
学生对象:
public class Student {
int A;
int B;
String C;
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
Student student = (Student) obj;
return A == student.A && B == student.B && C.equals(student.C);
}
}
编辑注意:ListA 和 ListB 可以有不同的行数
我建议你使用 retainAll
方法:
List<Student> listC = new ArrayList();
listC.addAll(listA);
listC.retainAll(listB); //now listC contains all double students
但您仍应覆盖 equals
方法
您可以使用 CollectionUtils
(Apache Commons) 中的 containsAny
方法:
if(CollectionUtils.containsAny(listA, listB)){
break;
}
一般方法是遍历第一个列表并检查元素是否包含在第二个列表中,如果存在则将元素添加到结果列表
下面是完整的解决方案
import java.util.ArrayList;
import java.util.List;
public class CompareListofObj {
public static void main(String[] args) {
List<Student> listStd1 = new ArrayList<Student>();
List<Student> listStd2 = new ArrayList<Student>();
Student std1 = new Student(1, 1, "a");
Student std2 = new Student(2, 1, "b");
Student std3 = new Student(3, 3, "c");
Student std4 = new Student(4, 4, "d");
listStd1.add(std1);
listStd1.add(std2);
listStd1.add(std3);
listStd1.add(std4);
Student std5 = new Student(1, 1, "a");
Student std6 = new Student(2, 1, "b");
Student std7 = new Student(7, 7, "c");
Student std8 = new Student(8, 8, "d");
listStd2.add(std5);
listStd2.add(std6);
listStd2.add(std7);
listStd2.add(std8);
List<Student> listResult = new ArrayList<Student>();
for (int i = 0; i < listStd1.size(); i++) {
if (listStd2.contains(listStd1.get(i))) {
listResult.add(listStd1.get(i));
} else {
}
}
for (int i = 0; i < listResult.size(); i++) {
System.out.println("common elt" + listResult.get(i).getA() + ", " + listResult.get(i).getB() + ", "
+ listResult.get(i).getC());
}
}
}
学生class
package sample;
public class Student {
int A;
int B;
String C;
public Student(int a, int b, String c) {
super();
A = a;
B = b;
C = c;
}
public int getA() {
return A;
}
public void setA(int a) {
A = a;
}
public int getB() {
return B;
}
public void setB(int b) {
B = b;
}
public String getC() {
return C;
}
public void setC(String c) {
C = c;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + A;
result = prime * result + B;
result = prime * result + ((C == null) ? 0 : C.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (A != other.A)
return false;
if (B != other.B)
return false;
if (C == null) {
if (other.C != null)
return false;
} else if (!C.equals(other.C))
return false;
return true;
}
}
removeAll命令是可行的方法,但是列表查找效率不高(线性时间),所以你得到一个O(n*m)的总时间(n是sizeA,m是sizeB);每个5000个条目,可能有点太多了。
如果可能,您应该将其更改为使用 Sets(并实现 Student 类 的 hashCode 和 equals 方法,以防您还没有实现!):
Set<Student> studentsA = new HashSet<>();
Set<Student> studentsB = new HashSet<>();
studentsA.removeAll(studentsB);
这让你 O(m*hash(n)).
我有两个学生对象列表(listA 和 listB),它们是通过从两个不同的数据库中查询而形成的。我需要迭代一个列表并确保它不存在于另一个列表中。
我使用了下面的比较代码,即覆盖 equals 方法并使用 for 循环进行比较。
假设列表 A 和列表 B 各有 5000 行,您能否建议是否有更好的实现方法?
对比码:
for (Student dataA:listA) {
for (Student dataB:listB) {
if(dataB.equals(dataA))
break;
}
}
学生对象:
public class Student {
int A;
int B;
String C;
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
Student student = (Student) obj;
return A == student.A && B == student.B && C.equals(student.C);
}
}
编辑注意:ListA 和 ListB 可以有不同的行数
我建议你使用 retainAll
方法:
List<Student> listC = new ArrayList();
listC.addAll(listA);
listC.retainAll(listB); //now listC contains all double students
但您仍应覆盖 equals
方法
您可以使用 CollectionUtils
(Apache Commons) 中的 containsAny
方法:
if(CollectionUtils.containsAny(listA, listB)){
break;
}
一般方法是遍历第一个列表并检查元素是否包含在第二个列表中,如果存在则将元素添加到结果列表 下面是完整的解决方案
import java.util.ArrayList;
import java.util.List;
public class CompareListofObj {
public static void main(String[] args) {
List<Student> listStd1 = new ArrayList<Student>();
List<Student> listStd2 = new ArrayList<Student>();
Student std1 = new Student(1, 1, "a");
Student std2 = new Student(2, 1, "b");
Student std3 = new Student(3, 3, "c");
Student std4 = new Student(4, 4, "d");
listStd1.add(std1);
listStd1.add(std2);
listStd1.add(std3);
listStd1.add(std4);
Student std5 = new Student(1, 1, "a");
Student std6 = new Student(2, 1, "b");
Student std7 = new Student(7, 7, "c");
Student std8 = new Student(8, 8, "d");
listStd2.add(std5);
listStd2.add(std6);
listStd2.add(std7);
listStd2.add(std8);
List<Student> listResult = new ArrayList<Student>();
for (int i = 0; i < listStd1.size(); i++) {
if (listStd2.contains(listStd1.get(i))) {
listResult.add(listStd1.get(i));
} else {
}
}
for (int i = 0; i < listResult.size(); i++) {
System.out.println("common elt" + listResult.get(i).getA() + ", " + listResult.get(i).getB() + ", "
+ listResult.get(i).getC());
}
}
}
学生class
package sample;
public class Student {
int A;
int B;
String C;
public Student(int a, int b, String c) {
super();
A = a;
B = b;
C = c;
}
public int getA() {
return A;
}
public void setA(int a) {
A = a;
}
public int getB() {
return B;
}
public void setB(int b) {
B = b;
}
public String getC() {
return C;
}
public void setC(String c) {
C = c;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + A;
result = prime * result + B;
result = prime * result + ((C == null) ? 0 : C.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (A != other.A)
return false;
if (B != other.B)
return false;
if (C == null) {
if (other.C != null)
return false;
} else if (!C.equals(other.C))
return false;
return true;
}
}
removeAll命令是可行的方法,但是列表查找效率不高(线性时间),所以你得到一个O(n*m)的总时间(n是sizeA,m是sizeB);每个5000个条目,可能有点太多了。
如果可能,您应该将其更改为使用 Sets(并实现 Student 类 的 hashCode 和 equals 方法,以防您还没有实现!):
Set<Student> studentsA = new HashSet<>();
Set<Student> studentsB = new HashSet<>();
studentsA.removeAll(studentsB);
这让你 O(m*hash(n)).