如何使用流Java8合并两个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

希望你能帮助我。我会尽量弄清楚问题的标题。 我有一个像这样的POJO

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();