首先创建一个类来处理这些数据。有两点需要注意。 equals 和 hashcode 方法仅基于 isbn 和 palletNumber 值,并且有一个 merge 方法返回 PackingListRow 的新实例,其数量介于此实例和您作为参数提供的其他实例之间。
class PackingListRow {
private final String isbn;
private final int palletNumber;
private final int quantity;
public PackingListRow(String isbn, int palletNumber, int quantity) {
this.isbn = isbn;
this.palletNumber = palletNumber;
this.quantity = quantity;
}
public String getIsbn() {
return isbn;
}
public int getPalletNumber() {
return palletNumber;
}
public int getQuantity() {
return quantity;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PackingListRow that = (PackingListRow) o;
return Objects.equals(palletNumber, that.palletNumber) &&
Objects.equals(isbn, that.isbn);
}
@Override
public int hashCode() {
return Objects.hash(isbn, palletNumber);
}
@Override
public String toString() {
return "PackingListRow{" +
"isbn='" + isbn + '\'' +
", palletNumber=" + palletNumber +
", quantity=" + quantity +
'}';
}
public PackingListRow merge(PackingListRow other) {
assert(this.equals(other));
return new PackingListRow(this.isbn, this.palletNumber, this.quantity + other.quantity);
}
}
一旦你有了它,你只需要创建另一个最初为空的新列表。它将包含合并的值。对于初始列表中的每个实例,您检查它是否已经在合并列表中。如果是,则通过调用合并来修改现有实例,否则只需将其附加到列表中。我们最终得到以下算法:
List<PackingListRow> list =
Arrays.asList(new PackingListRow("1234", 1, 10), new PackingListRow("1234", 2, 5), new PackingListRow("1234", 1, 15));
List<PackingListRow> mergedList = new ArrayList<>();
for(PackingListRow p : list) {
int index = mergedList.indexOf(p);
if(index != -1) {
mergedList.set(index, mergedList.get(index).merge(p));
} else {
mergedList.add(p);
}
}
System.out.println(mergedList);
哪些输出:
[PackingListRow{isbn='1234', palletNumber=1, quantity=25}, PackingListRow{isbn='1234', palletNumber=2, quantity=5}]
对于 Java 8,我可能会使用不同的策略(至少您表明有多种方法可以解决问题)。我会创建一个为我进行分组的静态类:
class PackingListRow {
private final String isbn;
private final int palletNumber;
private final int quantity;
static class GroupPacking {
private final String isbn;
private final int palletNumber;
public GroupPacking(PackingListRow p) {
this.isbn = p.isbn;
this.palletNumber = p.palletNumber;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GroupPacking that = (GroupPacking) o;
return Objects.equals(palletNumber, that.palletNumber) &&
Objects.equals(isbn, that.isbn);
}
@Override
public int hashCode() {
return Objects.hash(isbn, palletNumber);
}
}
....
public PackingListRow merge(PackingListRow other) {
assert (new GroupPacking(other).equals(new GroupPacking(this)));
return new PackingListRow(this.isbn, this.palletNumber, this.quantity + other.quantity);
}
}
然后您可以使用 Stream API。给定原始列表,您将获得一个Stream<PackingListRow>,您可以根据它们的 GroupPacking 实例(键)将元素收集到一个 Map 中。该值只是当前的PackingListRow 实例。如果您有两个具有相同 GroupPacking 值的实例(根据 equals/hashcode),则合并它们。你终于得到了地图的values()。
List<PackingListRow> mergedList =
new ArrayList<>(list.stream().collect(toMap(PackingListRow.GroupPacking::new, p -> p, PackingListRow::merge)).values());