删除具有重复字段值的entrySet对象

时间:2018-05-10 17:40:44

标签: java java-8 java-stream

我有Hashmap<String, List<A>>

目前我从我的条目列表中筛选出具有A.result null

的所有对象
map.entrySet().stream()
            .forEach(aList -> aList.getValue().removeIf(a -> a.result == null));

我还需要删除所有具有重复结果字段值的A对象

这样,如果我有A1.result = 1A2.result = 1,我就会得到一个。

编辑:移动临时解决方案作为答案,因为还没有找到更好的方法。

5 个答案:

答案 0 :(得分:1)

正如Hemant在their comment中所述,在Object#equals中覆盖Object#hashCodeA是明智之举,因此可以通过{{1}来比较两个对象field:

result

现在,您可以回忆一下@Override public boolean equals(Object o) { if (!(o instanceof A)) { return false; } return Objects.equals(result, ((A) o).result); } @Override public int hashCode() { return Objects.hash(result); } Map,这可以通过Java 10中的以下内容完成:

Map<String, Set<A>>

在Java 8中略有不同:

map.entrySet()
   .stream()
   .collect(Collectors.toMap(Map.Entry::getKey, e -> Set.copyOf(e.getValue()))));

答案 1 :(得分:0)

也许使用Set来完成你的任务?在forEach中,你可以添加set的初始化,然后在那里添加你的值。当您调用add()方法时,如果值已经在集合中,则返回false,因此您将对其进行过滤。这是我的代码片段,我使用的是List,但您可以将其替换为A类

public static void main(String[] args) {
    HashMap<String, List<Integer>> factDwhResultMap = new HashMap<>();
    factDwhResultMap.put("k1", new ArrayList<>(Arrays.asList(1,2,3,3,null)));
    factDwhResultMap.put("k2", new ArrayList<>(Arrays.asList(null,7,7,7,null)));

    factDwhResultMap.entrySet().stream().forEach(aList -> {
         Set resultSet = new HashSet();
         aList.getValue().removeIf(a -> a == null || !resultSet.add(a));
         System.out.println(aList);
         });
}

输出

k1=[1, 2, 3]
k2=[7]

答案 2 :(得分:0)

它不是一个非常优雅的,因为它创建临时对象(地图,列表)

actDwhResultMap.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue()
                .stream()
                .filter(a -> a.result != null)
                .collect(Collectors.collectingAndThen(Collectors
                                    .toMap(a -> a.result,
                                        java.util.function.Function.identity(),
                                        ((a1, a2) -> a1),
                                        LinkedHashMap::new),
                        result -> new ArrayList<>(result.values())))
        ));

迭代遍历映射条目,并为每个值(List<A>)创建一个由A.result键控的临时映射(LinkedHashMap以维护插入顺序),如果有两个对象具有相同的result ,它选择了第一个。

最后(在传递给collectingAndThen的函数中),它将值作为List返回。然后将其插入到由原始地图条目的键键入的新地图中。

答案 3 :(得分:0)

临时解决方案:

List<String> results= new ArrayList<>();    
map.entrySet().stream()
        .forEach(aList -> 
            aList.getValue().removeIf(a -> {
                if (a.result == null) {
                    return true;
                }
                if (results.stream().filter(result -> result.equalsIgnoreCase(a.result)).count() > 0) {
                    return true;
                }
                results.add(a.result);
                return false;
            }));

答案 4 :(得分:0)

为谓词

创建工厂方法
public static Predicate<A> nullOrDuplicate() {
    Set<Object> set = new HashSet<>();
    set.add(null);
    return a -> !set.add(a.result);
}

然后,您可以像

一样执行操作
Map<String, List<A>> map;
...
map.values().forEach(list -> list.removeIf(nullOrDuplicate()));