如何比较两个对象列表之间的字段?

Gia*_*uca 1 java collections list

假设我有一个看起来像这样的对象:

public class Supermarket {

    public String supermarketId;
    public String lastItemBoughtId;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

我有两个超市列表,一个是“旧”,另一个是“新”(即一个是本地的,另一个是从云中检索的)。

List<Supermarket> local = getFromLocal();
List<Supermarket> cloud = getFromCloud();
Run Code Online (Sandbox Code Playgroud)

我想找到所有彼此不同的Supermarket对象(给定的supermarketIdlastItemBoughtId

我想到的第一个解决方案是迭代第一个List,然后在第一次迭代内迭代第二个,每次每次local.get(i).supermarketId.equals(cloud.get(j).supermarketId),检查元素的是否lastItemBoughtIdi元素的id不同j。如果不同,则将整个Supermarket对象添加到新列表中。

更清楚地说,是这样的:

List<Supermarket> difference = new ArrayList<>();
for (Supermarket localSupermarket : local) {
    for (Supermarket cloudSupermarket : cloud) {
        if (localSupermarket.supermarketId.equals(cloudSupermarket.supermarketId) &&
        !localSupermarket.lastItemBoughtId.equals(cloudSupermarket.lastItemBoughtId))
            difference.add(cloudSupermarket);
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,这看起来大大低效。有没有更好的方法来处理这种情况?

小智 5

一种解决方案:

  1. 通过遍历列表一次,以超级市场编号为关键字构建本地超级市场的​​地图
  2. 遍历云列表并进行比较,从地图中查找当地的超级市场。

即O(n)而不是O(n 2

这是两行解决方案:

Map<String, Supermarket> map = getFromLocal().stream()
    .collect(Collectors.toMap(s -> s.supermarketId, s -> s));
List<Supermarket> hasDiffLastItem = getFromCloud().stream()
    .filter(s -> !map.get(s.supermarketId).lastItemBoughtId.equals(s.lastItemBoughtId))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)