有效地比较两个大型 Java 列表以找到独特的项目

问题描述 投票:0回答:3

我如何有效地比较 Java 中的两个大型对象列表,并识别一个列表中存在但另一个列表中不存在的项目?

例子:

假设我有两个包含数千名员工数据的大型 CSV 文件,其中包含姓名、部门和薪水列。需要比较两个文件并根据姓名和部门识别一个文件中存在但另一个文件中不存在的任何员工。

public static void compareCSVFiles(String file1, String file2) {
List<Employee> list1 = readCSVFile(file1);
List<Employee> list2 = readCSVFile(file2);

List<Employee> uniqueTo1 = new ArrayList<>();
List<Employee> uniqueTo2 = new ArrayList<>();

for (Employee emp1 : list1) {
    boolean found = false;
    for (Employee emp2 : list2) {
        if (emp1.getName().equals(emp2.getName()) && emp1.getDepartment().equals(emp2.getDepartment())) {
            found = true;
            break;
        }
    }
    if (!found) {
        uniqueTo1.add(emp1);
    }
}

for (Employee emp2 : list2) {
    boolean found = false;
    for (Employee emp1 : list1) {
        if (emp2.getName().equals(emp1.getName()) && emp2.getDepartment().equals(emp1.getDepartment())) {
            found = true;
            break;
        }
    }
    if (!found) {
        uniqueTo2.add(emp2);
    }
}

System.out.println("Employees unique to " + file1 + ":");
for (Employee emp : uniqueTo1) {
    System.out.println(emp.getName() + " (" + emp.getDepartment() + ")");
}

System.out.println("Employees unique to " + file2 + ":");
for (Employee emp : uniqueTo2) {
    System.out.println(emp.getName() + " (" + emp.getDepartment() + ")");
    }
 }
  • 代码逐行读取 CSV 文件并将每一行存储为字符串。对于大文件,这可能不是内存高效或可扩展的。
  • 代码使用嵌套循环将一个列表中的每个员工与另一个列表中的每个员工进行比较,这对于大文件来说可能很慢且效率低下。
  • 该代码仅标识一个列表中唯一的员工,但 不是另一个。它不识别存在于 两个列表。

认为我们可以更有效地编写这些代码。想知道你对此的想法。 谢谢!

java list performance object comparison
3个回答
0
投票

不使用列表,而是使用具有唯一标识符的地图(例如员工 ID) 然后运行第二个列表/地图以查看第一个地图是否包含它。

仅此一项就可以为您节省大量的复杂性/时间


0
投票

您可以将它们加载到集合中(根据相等标准实现哈希码/等于)并相交/差异。如果内容适合内存,这将起作用。
如果您想要一个可扩展的解决方案,您可以在磁盘合并排序上对它们进行排序并逐行扫描。
最后,如果您想要一个真正可扩展的解决方案,那么请使用 Spark。


0
投票

如果列表相等,则为 O(n) 操作。您可以使用:

Assert.assertEquals(list1, list2);

这依赖于 List::equals 来比较列表。

如果列表不相等,您将得到一个显示差异的异常。

因此,如果你想比较列表中的对象,你可以使用:

例如:

Arraylist a = {obj1, obj2, obj3};
Arraylist b={obj1, obj5, obj6};

List<Object> c = new ArrayList<Object>(a);
c.removeAll(b);

同样,考虑使用集合而不是列表。

© www.soinside.com 2019 - 2024. All rights reserved.