我有一类带有字段日期、ID 和操作的 Item。就我而言,我有旧项目列表和另一个列表,其中包括旧项目和新项目,所以我想过滤掉旧项目,所以我不会介意它们。例如,我遍历新项目,只使用不属于旧项目列表的项目。
使用 for 循环,它看起来像这样,但我想重写它的功能方式
List<Item> filteredList = new ArrayList<>();
for (Item item : newList) {
for (Item oldItem : oldList) {
if (!item.getDate().equals(oldItem.getDate()) && !item.getId().equals(oldItem.getId()) && !item.getAction().equals(oldItem.getAction())) {
filteredList.add(item);
}
}
}
首先,我建议在Item
类中实现一个equals
方法,以避免这种复杂的情况(我不确定是否正确,顺便说一句(。
其次,为了使搜索更有效率,将旧列表的元素放在一个HashSet
中,以允许恒定的时间查找。这将需要覆盖Item
类的equals
和hashCode
。
最后,代码将如下所示:
List<Item> filteredList =
newList.stream()
.filter(i -> !oldList.contains(i)) // oldList should be replaced with a HashSet
// for better performance
.collect(Collectors.toList());
HashSet
:
Set<Item> oldSet = new HashSet<>(oldList);
List<Item> filteredList =
newList.stream()
.filter(i -> !oldSet.contains(i))
.collect(Collectors.toList());
关于您的病情:
if (!item.getDate().equals(oldItem.getDate()) && !item.getId().equals(oldItem.getId()) && !item.getAction().equals(oldItem.getAction()))
这似乎是错误的,因为如果具有不同 ID 的两个项目将具有相同的日期(或操作(,它们将无法通过测试。
我相信你打算写:
if (!item.getDate().equals(oldItem.getDate()) || !item.getId().equals(oldItem.getId()) || !item.getAction().equals(oldItem.getAction()))
这意味着,如果两个项在 3 个属性中的至少一个属性上不同,则认为它们彼此不同。
首先,你应该在Item
类中实现equals()
方法(以及.hashCode()
(,以便你可以正确地比较项目,例如,使用List
的.contains()
方法时将需要它。
然后,您可以使用.contains()
方法来测试当前项是否存在于oldList
中,并根据该结果筛选项。
在 Java 8 中,您的代码应如下所示:
List<Item> result = newList.stream()
.filter(line -> !oldList.contains(line))
.collect(Collectors.toList());
注意:
请注意,此处使用stream
并不是真正必要的,因为您可以使用List
方法来实现这一点,例如.retainAll()
这将允许您以更好的方式过滤newList
。
此任务不需要流。只需使用List.removeAll
方法,它就可以完全按照您的要求:
oldList.removeAll(newList);
这要求Item
类实现equals()
方法,以便可以比较元素的相等性并删除。
如果您不想更改原始oldList
,则可以创建一个新列表,然后从中删除元素:
List<Item> filteredList = new ArrayList<>(oldList);
filteredList.removeAll(newList);
另一种更实用的方法是使用Collection.removeIf
方法:
oldList.removeIf(item -> newList.contains(item));
或者只是:
oldList.removeIf(newList::contains);
这仍然需要Item
类来实现equals()
方法。但是,它也是低效的,因为List.contains
需要遍历整个newList
来检查每个oldList
项目是否属于它。更有效的方法是使用HashSet
:
Set<Item> newSet = new HashSet<>(newList);
然后,使用上述removeIf
:
oldList.removeIf(newSet::contains);
这种方法不仅要求Item
类实现equals()
方法,还要求hashCode
方法,该方法必须符合Object
类关于相等的契约。