gpt4 book ai didi

java 8 如果不存在,则将 List 的所有元素合并到 List 中

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:56:58 25 4
gpt4 key购买 nike

我需要将 listB 的所有元素合并到另一个列表 listA 中。

如果 listA 中已经存在某个元素(基于自定义相等性检查),我不想添加它。

我不想使用 Set,也不想覆盖 equals() 和 hashCode()。

原因是,我不想防止 listA 本身出现重复,我只想在 listA 中已经存在我认为相等的元素时不从 listB 合并。

我不想覆盖 equals() 和 hashCode(),因为这意味着我需要确保我对元素的 equals() 实现在任何情况下都适用。然而,listB 中的元素可能未完全初始化,即它们可能缺少对象 ID,而该对象 ID 可能存在于 listA 的元素中。

我目前的方法涉及一个接口(interface)和一个实用函数:

public interface HasEqualityFunction<T> {

public boolean hasEqualData(T other);
}

public class AppleVariety implements HasEqualityFunction<AppleVariety> {
private String manufacturerName;
private String varietyName;

@Override
public boolean hasEqualData(AppleVariety other) {
return (this.manufacturerName.equals(other.getManufacturerName())
&& this.varietyName.equals(other.getVarietyName()));
}

// ... getter-Methods here
}


public class CollectionUtils {
public static <T extends HasEqualityFunction> void merge(
List<T> listA,
List<T> listB) {
if (listB.isEmpty()) {
return;
}
Predicate<T> exists
= (T x) -> {
return listA.stream().noneMatch(
x::hasEqualData);
};
listA.addAll(listB.stream()
.filter(exists)
.collect(Collectors.toList())
);
}
}

然后我会像这样使用它:

...
List<AppleVariety> appleVarietiesFromOnePlace = ... init here with some elements
List<AppleVariety> appleVarietiesFromAnotherPlace = ... init here with some elements
CollectionUtils.merge(appleVarietiesFromOnePlace, appleVarietiesFromAnotherPlace);
...

在 listA 中获取我的新列表,所有元素都从 B 中合并。

这是一个好方法吗?是否有更好/更简单的方法来完成同样的任务?

最佳答案

你想要这样的东西:

public static <T> void merge(List<T> listA, List<T> listB, BiPredicate<T, T> areEqual) {
listA.addAll(listB.stream()
.filter(t -> listA.stream().noneMatch(u -> areEqual.test(t, u)))
.collect(Collectors.toList())
);
}

您不需要 HasEqualityFunction 接口(interface)。您可以重用 BiPredicate 来测试这两个对象在您的逻辑中是否相等。

此代码根据给定的谓词仅过滤 listB 中不包含在 listA 中的元素。它遍历 listA 的次数与 listB 中的元素数一样多。


另一种性能更好的实现方式是使用一个包装器类来包装您的元素,并将谓词作为 equals 方法:

public static <T> void merge(List<T> listA, List<T> listB, BiPredicate<T, T> areEqual, ToIntFunction<T> hashFunction) {

class Wrapper {
final T wrapped;
Wrapper(T wrapped) {
this.wrapped = wrapped;
}
@Override
public boolean equals(Object obj) {
return areEqual.test(wrapped, ((Wrapper) obj).wrapped);
}
@Override
public int hashCode() {
return hashFunction.applyAsInt(wrapped);
}
}

Set<Wrapper> wrapSet = listA.stream().map(Wrapper::new).collect(Collectors.toSet());

listA.addAll(listB.stream()
.filter(t -> !wrapSet.contains(new Wrapper(t)))
.collect(Collectors.toList())
);
}

这首先将每个元素包装在一个 Wrapper 对象中,并将它们收集到一个 Set 中。然后,它过滤 listB 中不包含在该集合中的元素。相等性测试是通过委托(delegate)给定的谓词来完成的。约束是我们还需要提供一个 hashFunction 来正确实现 hashCode

示例代码为:

List<String> listA = new ArrayList<>(Arrays.asList("foo", "bar", "test"));
List<String> listB = new ArrayList<>(Arrays.asList("toto", "foobar"));
CollectionUtils.merge(listA, listB, (s1, s2) -> s1.length() == s2.length(), String::length);
System.out.println(listA);

关于java 8 如果不存在,则将 List 的所有元素合并到 List 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36198025/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com