所以我有一些示例代码正在尝试找出下面的逻辑。它只是一个主要的主要方法和两个POJO,但是它将运行。我正在调试以在终止点获取值。
public class Main {
public static void main(String[] args) {
obj1 obj1 = new obj1();
obj1 obj12 = new obj1();
obj2 obj2 = new obj2();
obj2 obj22 = new obj2();
obj1.id = 123L;
obj1.carId = 1234L;
obj12.id = 123L;
obj12.carId = 1234L;
obj2.carId = 1234L;
obj22.carId = 12345L;
ArrayList<obj1> obj1Arr = new ArrayList<>();
ArrayList<obj2> obj2Arr = new ArrayList<>();
obj1Arr.add(obj1);
obj1Arr.add(obj12);
obj2Arr.add(obj2);
obj2Arr.add(obj22);
List<obj2> newCarList= obj2Arr.stream()
.filter(anObjOf2 -> obj1Arr
.stream()
.anyMatch(carReg -> carReg.getCarId().equals(anObjOf2.getCarId())))
.collect(Collectors.toList());
}
}
POJO1:
public class obj1 {
Long id = null;
Long carId = null;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getCarId() {
return carId;
}
public void setCarId(Long carId) {
this.carId = carId;
}
}
POJO2:
public class obj2 {
Long id = null;
Long carId = null;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getCarId() {
return carId;
}
public void setCarId(Long carId) {
this.carId = carId;
}
}
如您所见,我正在流式传输并过滤掉obj
上不匹配的所有carId
。我的下一个目标是在匹配的对象上set
id
(不是carId)。
基本上,如果obj1.carId == obj2.carId
然后是set obj1.id = obj2.id
。
我的问题是我不知道如何在同一流中执行此操作。可能吗?我忍不住想,此时需要迭代器吗?
答案 0 :(得分:3)
请勿在一个流中执行这两个操作。这是一个非常糟糕的风格。
首先收集数据。然后突变元素。像这样:
Map<obj2, Optional<obj1>> map =
obj2Arr.stream()
.collect(toMap(identity(), o2 -> obj1Arr.stream()
.filter(o1 -> o1.getCarId().equals(o2.getCarId()))
.findAny()));
map.forEach((o1, optO2) -> optO2.ifPresent(o2 -> o1.setId(o2.id)));
否则,您可以只使用嵌套的for-each循环。
答案 1 :(得分:2)
我建议首先为第一个列表中的每个元素创建一个Map
到carId
的映射(我对您的类做了一些修改,以使其更易读和删除。重复的ID,我认为这是一个错误):
id
然后,您可以使用此@Data @AllArgsConstructor
class Car {
Long id = null;
Long carId = null;
}
List<Car> obj1Arr = Arrays.asList(new Car(1L, 123L), new Car(2L, 1234L));
List<Car> obj2Arr = Arrays.asList(new Car(0L, 1234L), new Car(0L, 12345L));
Map<Long, Long> carIdToId = obj1Arr.stream()
.collect(Collectors.toMap(Car::getCarId, Car::getId));
// [Car(id=2, carId=1234), Car(id=0, carId=12345)]
来过滤具有相同Map
的汽车,而不必与其他汽车进行比较。然后,使用carID
仅在原始列表中设置ID。
forEach
如果只想让{em {em} 等于obj2Arr.stream()
.filter(anObjOf2 -> carIdToId.containsKey(anObjOf2.getCarId()))
.forEach(anObjOf2 -> anObjOf2.setId(carIdToId.get(anObjOf2.getCarId())));
System.out.println(obj2Arr);
// [Car(id=2, carId=1234), Car(id=0, carId=12345)]
,则可以在carId
和peek
中设置ID。不过,这仍然会修改原始实例:
collect
或创建一个全新实例的列表:
obj2Arr = obj2Arr.stream()
.filter(anObjOf2 -> carIdToId.containsKey(anObjOf2.getCarId()))
.peek(anObjOf2 -> anObjOf2.setId(carIdToId.get(anObjOf2.getCarId())))
.collect(Collectors.toList());
System.out.println(obj2Arr);
// [Car(id=2, carId=1234)]
答案 2 :(得分:1)
您可以在谓词anyMatch
List<obj2> newCarList= obj2Arr.stream()
.filter(anObjOf2 -> obj1Arr
.stream()
.anyMatch(carReg -> {
if(carReg.getCarId().equals(anObjOf2.getCarId()))) {
carReg.setId(anObjOf2.getId());
return true;
}
return false;
}).collect(Collectors.toList());
第二种方法
先过滤
List<obj2> newCarList= obj2Arr.stream()
.filter(anObjOf2 -> obj1Arr
.stream()
.anyMatch(carReg -> carReg.getCarId().equals(anObjOf2.getCarId())))
.collect(Collectors.toList());
现在设置ID
newCarList.forEach(obj->{
obj1Arr.forEach(o-> {
if(o.getCarId().equals(obj.getCarId()) {
o.setId(obj.getId());
}
};
});
答案 3 :(得分:1)
如果 O(m*n)
解决方案适合您,那么更简单的实现将使用for
循环,如下所示:
// classes renamed for naming convention and relatiing to question at the same time
List<ObjectTwo> newCarList = new ArrayList<>();
for(ObjectTwo objectTwo: objectTwoArr) {
for (ObjectOne objectOne : objectOneArr) {
if (objectTwo.getCarId().equals(objectOne.getCarId())) {
objectOne.setId(objectTwo.getId());
newCarList.add(objectTwo);
}
}
}
m
和n
是列表的大小。