首页 > 解决方案 > 使用单个匹配字段删除 java 流中的特定重复项

问题描述

给定一个包含以下字段的 java pojo

public class Pojo { 
    // for brevity I am excluding the property getters / setters etc.
    private int V;
    private BigDecimal Amount;
    private String Operation;
    private String Tag;
    private String Code; 
}

我有一个看起来像这样的 pojos 列表。如果我专门比较标签、数量、版本并忽略代码,我想使用散列/流/任何东西来删除相同标签、数量正好有 1 个“IU”和正好有 1 个“DU”的所有行,和版本。

有没有办法加入或分组流以确保如果对于相同的值恰好有 1 个插入更新“IU”和恰好 1 个删除更新“DU”,那么两者都被删除?

Ver Amount  Operation   Tag     Code

1   1       "IU"        6896450 5500 
1   1       "DU"        6898103 5500 
2   4       "IU"        6954561 5200 
2   4       "DU"        6954561 5500 
3   4       "IU"        7057717 5200 
3   4       "DU"        7057717 5500 
1   8       "IU"        7132952 5200 
1   8       "DU"        7132952 5500 

标签: java

解决方案


// import static java.util.stream.Collectors.groupingBy;

List<Pojo> pojos = new ArrayList<>(Arrays.asList(
    new Pojo(1, BigDecimal.ONE, "IU", "6896450", "5500"),
    // ...,
    new Pojo(1, BigDecimal.valueOf(8), "DU", "7132952", "5500")));

// Create a map (`opMapByTag`) by `Tag`,
// within the results/pojos create another map (`pojosByOp`) by `Operation`
Map<String, Map<String, List<Pojo>>> opMapByTag =
    pojos.stream().collect(
        groupingBy(Pojo::getTag,
           groupingBy(Pojo::getOperation)));

Set<Pojo> toBeRemoved = new HashSet<>();

for (Entry<String, Map<String, List<Pojo>>> e : opMapByTag.entrySet())
{
  Map<String, List<Pojo>> pojosByOp = e.getValue();
  List<Pojo> l1, l2;
  if ((pojosByOp.size() == 2) &&
      ((l1 = pojosByOp.get("IU")).size() == 1) &&
      ((l2 = pojosByOp.get("DU")).size() == 1))
  {
    Collections.addAll(toBeRemoved, l1.get(0), l2.get(0));
  }
}

pojos.removeIf(toBeRemoved::contains);

pojos.forEach(System.out::println);

推荐阅读