在两个对象数组列表中查找唯一字符串
Finding unique strings in two arraylists of objects
我有两个对象数组列表,我想知道哪些字符串是arraylist 1独有的,哪些字符串是arraylist 2独有的。我想到的是下面的forloop,我必须实现两次, 反转数组列表的位置。我希望有人可以建议一种更优雅的方法来做到这一点。
根据请求,我想我错误地认为代码片段本身隐含了更多内容。这产生的输出是:
第二个 arrayList 中不存在葡萄
第一个 arrayList 中不存在菠萝
效果很好,一切都很好,但是,根据以上内容,我希望通常对 streams/java 有更多了解的人可以提供比 运行 我的流两次更好的解决方案,输入反转。
import java.util.ArrayList;
public class CompareTwoArrays {
ArrayList<MyCustomObject> firstArrayListOfObjects = new ArrayList<>();
ArrayList<MyCustomObject> secondArrayListOfObjects = new ArrayList<>();
public void superSpecificExampleMethod() {
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "apple"));
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "orange"));
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "banana"));
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "grape"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "apple"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "pineapple"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "orange"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "banana"));
for (MyCustomObject object : firstArrayListOfObjects) {
if (!secondArrayListOfObjects.stream().map(MyCustomObject::getString).filter(object.getString()::equals).findFirst().isPresent()) {
System.out.println(object.getString() + " doesn't exist in second arrayList");
}
}
for (MyCustomObject object : secondArrayListOfObjects) {
if (!firstArrayListOfObjects.stream().map(MyCustomObject::getString).filter(object.getString()::equals).findFirst().isPresent()) {
System.out.println(object.getString() + " doesn't exist in first arrayList");
}
}
}
}
class MyCustomObject {
private int randomIntOne;
private int randomIntTwo;
private String string;
public MyCustomObject(int randomIntOne, int randomIntTwo, String string) {
this.randomIntOne = randomIntOne;
this.randomIntTwo = randomIntTwo;
this.string = string;
}
public String getString() {
return string;
}
}
假设有两个对象数组列表 MyObject
包含字符串:
List<MyObject> listOne = new ArrayList<>(Arrays.asList(
new MyObject("aaa"), new MyObject("bbb"), new MyObject("ccc"), new MyObject("ddd")
));
List<MyObject> listTwo = new ArrayList<>(Arrays.asList(
new MyObject("fff"), new MyObject("bbb"), new MyObject("ggg"), new MyObject("ddd")
));
要在 listOne
中找到那些在 listTwo
中不可用的“独特”对象,有几种方法:
- 使用
List::removeAll
,前提是 equals
和 hashCode
方法在此 class 中正确实现
removeAll
应应用于 listOne
的副本
List<MyObject> diffOneMinusTwo = new ArrayList<>(listOne); // copy
diffOneMinusTwo.removeAll(listTwo); // ["aaa", "ccc"]
- 使用
List::removeIf
接受谓词并使用listTwo
的对象中包含的一组字符串:
Set<String> listTwoStrings = listTwo
.stream()
.map(MyObject::getString)
.collect(Collectors.toSet);
List<MyObject> diffOneMinusTwo = new ArrayList<>(listOne); // copy
diffOneMinusTwo.removeIf(x -> listTwoStrings.contains(x.getString()));
- 使用流 API
filter
和 collect
- 这里不需要复制,但使用了一组临时字符串
List<MyObject> diffOneMinusTwo = listOne
.stream()
.filter(x -> !listTwoStrings.contains(x.getString()))
.collect(Collectors.toList());
在 Java 11 中有静态 Predicate::not
方法,所以流版本可能如下所示(如果正确实现 hashCode
和 equals
):
List<MyObject> diffOneMinusTwo = listOne
.stream()
.filter(Predicate.not(listTwo::contains)) // using method reference
.collect(Collectors.toList());
listTwo
和listOne
之间的区别可以反之亦然
我有两个对象数组列表,我想知道哪些字符串是arraylist 1独有的,哪些字符串是arraylist 2独有的。我想到的是下面的forloop,我必须实现两次, 反转数组列表的位置。我希望有人可以建议一种更优雅的方法来做到这一点。
根据请求,我想我错误地认为代码片段本身隐含了更多内容。这产生的输出是:
第二个 arrayList 中不存在葡萄
第一个 arrayList 中不存在菠萝
效果很好,一切都很好,但是,根据以上内容,我希望通常对 streams/java 有更多了解的人可以提供比 运行 我的流两次更好的解决方案,输入反转。
import java.util.ArrayList;
public class CompareTwoArrays {
ArrayList<MyCustomObject> firstArrayListOfObjects = new ArrayList<>();
ArrayList<MyCustomObject> secondArrayListOfObjects = new ArrayList<>();
public void superSpecificExampleMethod() {
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "apple"));
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "orange"));
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "banana"));
firstArrayListOfObjects.add(new MyCustomObject(1, 1, "grape"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "apple"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "pineapple"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "orange"));
secondArrayListOfObjects.add(new MyCustomObject(1, 1, "banana"));
for (MyCustomObject object : firstArrayListOfObjects) {
if (!secondArrayListOfObjects.stream().map(MyCustomObject::getString).filter(object.getString()::equals).findFirst().isPresent()) {
System.out.println(object.getString() + " doesn't exist in second arrayList");
}
}
for (MyCustomObject object : secondArrayListOfObjects) {
if (!firstArrayListOfObjects.stream().map(MyCustomObject::getString).filter(object.getString()::equals).findFirst().isPresent()) {
System.out.println(object.getString() + " doesn't exist in first arrayList");
}
}
}
}
class MyCustomObject {
private int randomIntOne;
private int randomIntTwo;
private String string;
public MyCustomObject(int randomIntOne, int randomIntTwo, String string) {
this.randomIntOne = randomIntOne;
this.randomIntTwo = randomIntTwo;
this.string = string;
}
public String getString() {
return string;
}
}
假设有两个对象数组列表 MyObject
包含字符串:
List<MyObject> listOne = new ArrayList<>(Arrays.asList(
new MyObject("aaa"), new MyObject("bbb"), new MyObject("ccc"), new MyObject("ddd")
));
List<MyObject> listTwo = new ArrayList<>(Arrays.asList(
new MyObject("fff"), new MyObject("bbb"), new MyObject("ggg"), new MyObject("ddd")
));
要在 listOne
中找到那些在 listTwo
中不可用的“独特”对象,有几种方法:
- 使用
List::removeAll
,前提是equals
和hashCode
方法在此 class 中正确实现
removeAll
应应用于 listOne
List<MyObject> diffOneMinusTwo = new ArrayList<>(listOne); // copy
diffOneMinusTwo.removeAll(listTwo); // ["aaa", "ccc"]
- 使用
List::removeIf
接受谓词并使用listTwo
的对象中包含的一组字符串:
Set<String> listTwoStrings = listTwo
.stream()
.map(MyObject::getString)
.collect(Collectors.toSet);
List<MyObject> diffOneMinusTwo = new ArrayList<>(listOne); // copy
diffOneMinusTwo.removeIf(x -> listTwoStrings.contains(x.getString()));
- 使用流 API
filter
和collect
- 这里不需要复制,但使用了一组临时字符串
List<MyObject> diffOneMinusTwo = listOne
.stream()
.filter(x -> !listTwoStrings.contains(x.getString()))
.collect(Collectors.toList());
在 Java 11 中有静态 Predicate::not
方法,所以流版本可能如下所示(如果正确实现 hashCode
和 equals
):
List<MyObject> diffOneMinusTwo = listOne
.stream()
.filter(Predicate.not(listTwo::contains)) // using method reference
.collect(Collectors.toList());
listTwo
和listOne
之间的区别可以反之亦然