如何使用流Java8合并两个POJO列表,必要时修改一些值
希望你能帮助我。我会尽量弄清楚问题的标题。 我有一个像这样的POJO如何使用流Java8合并两个POJO列表,必要时修改一些值,java,java-8,java-stream,Java,Java 8,Java Stream,希望你能帮助我。我会尽量弄清楚问题的标题。 我有一个像这样的POJO public class Factor { private int id; private String item; private int unitId; private Double factor; // constructor getters and setters } 我有两个此类的列表,其中包含来自两个不同数据库中两个不同表的数据 equals方法是这样定义的 import
public class Factor {
private int id;
private String item;
private int unitId;
private Double factor;
// constructor getters and setters
}
我有两个此类的列表
,其中包含来自两个不同数据库中两个不同表的数据
equals
方法是这样定义的
import com.google.common.base.Objects;
//....
@Override
public boolean equals( Object o ) {
if ( this == o )
return true;
if ( o == null || getClass() != o.getClass() )
return false;
Factor that = (Factor) o;
return getUnitId() == that.getUnitId() &&
Objects.equal(getItem(), that.getItem());
}
因此,当两个对象具有相同的item
和unitId
属性时,它们被认为是相等的
假设我有以下两个列表:
List<Factor> listA = new ArrayList<>();
listA.add(new Factor(1, "Item1", 1, 0.5));
listA.add(new Factor(2, "Item1", 2, 0.6));
listA.add(new Factor(3, "Item2", 1, 1.0));
listA.add(new Factor(4, "Item3", 1, 2.0));
List<Factor> listB = new ArrayList<>();
listB.add(new Factor(0, "Item1", 1, 0.8));
listB.add(new Factor(0, "Item1", 2, 0.9));
listB.add(new Factor(0, "Item4", 1, 1.0));
listB.add(new Factor(0, "Item5", 1, 2.0));
我知道如何将这两个列表与流进行比较,并过滤哪些对象是相等的或不同的,但有人知道如何将相等的对象组合在一起得到一个新对象吗?您正在寻找一个“zip”函数。然而,流API中没有一个(至少在Java8中,我不知道更新的版本)
您可以在中找到如何编写zip
方法
使用siki的答案,我们得到以下方法:
public static<A, B, C> Stream<C> zip(Stream<? extends A> a,
Stream<? extends B> b,
BiFunction<? super A, ? super B, ? extends C> zipper) {
Objects.requireNonNull(zipper);
Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();
// Zipping looses DISTINCT and SORTED characteristics
int characteristics = aSpliterator.characteristics() & bSpliterator.characteristics() &
~(Spliterator.DISTINCT | Spliterator.SORTED);
long zipSize = ((characteristics & Spliterator.SIZED) != 0)
? Math.min(aSpliterator.getExactSizeIfKnown(), bSpliterator.getExactSizeIfKnown())
: -1;
Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
Iterator<C> cIterator = new Iterator<C>() {
@Override
public boolean hasNext() {
return aIterator.hasNext() && bIterator.hasNext();
}
@Override
public C next() {
return zipper.apply(aIterator.next(), bIterator.next());
}
};
Spliterator<C> split = Spliterators.spliterator(cIterator, zipSize, characteristics);
return (a.isParallel() || b.isParallel())
? StreamSupport.stream(split, true)
: StreamSupport.stream(split, false);
}
假设您还重写了hashCode
方法,您可以使用toMap
收集器:
Collection<Factor> values = Stream.concat(listA.stream(), listB.stream())
.collect(Collectors.toMap(Function.identity(),
Function.identity(), (a, b) -> {
return new Factor(a.getId(), a.getItem(), a.getUnitId(), b.getFactor());
})).values();
Collection values=Stream.concat(listA.Stream(),listB.Stream())
.collect(Collectors.toMap(Function.identity()),
Function.identity(),(a,b)->{
返回新的因子(a.getId(),a.getItem(),a.getUnitId(),b.getFactor());
})).values();
只是一个问题,列表必须具有相同的大小吗?@pburgov列表不必具有相同的大小。结果列表将与两个列表中较短的列表一样长。你是对的,项目的顺序很重要。否则,您将如何决定哪个项目对应于哪个项目?ID为1的项目的系数应该是0.9还是0.8@AdrianThank谢谢你@Sweeper的回答。这就是我要找的!!
List<Factor> result = zip(list1.stream(), list2.stream(),
(x, y) -> x.equals(y) ? new Factor(x.getId(), y.getItem(), y.getUnitId(), y.getFactor()) : y) // you might want to create a copy of y instead
.collect(Collectors.toList());
new Factor(y.getID(), y.getItem(), y.getUnitId(), y.getFactor())
Collection<Factor> values = Stream.concat(listA.stream(), listB.stream())
.collect(Collectors.toMap(Function.identity(),
Function.identity(), (a, b) -> {
return new Factor(a.getId(), a.getItem(), a.getUnitId(), b.getFactor());
})).values();