在TreeMap上应用Distinct函数

时间:2014-09-18 06:15:15

标签: java lambda distinct java-8 treemap

代码:

   Map<Integer, HashSet<String>> test = new TreeMap<>();
    test.put(1, new HashSet<>());
    test.put(2, new HashSet<>());
    test.put(3, new HashSet<>());
    test.put(4, new HashSet<>());

    test.get(1).add("1");
    test.get(2).add("2");
    test.get(3).add("2");
    test.get(4).add("3, 33");

    //get value of treemap and get rid of the duplicate by using distinct and printout 
    //at the end
    test.values().stream().distinct().forEach(i -> System.out.println(i));

输出:

[1]
[2]
[3, 33]

我的问题是如何在没有重复值的情况下同时打印出键和值?

预期结果:

  1= [1]
  2= [2]
  3= [3, 33]

我甚至尝试下面的代码,但它给了我带有重复值的树形图:

代码:

   List<Map.Entry<Integer, HashSet<String>>> list = new ArrayList<>();
   list.addAll(test.entrySet());
   list.stream().distinct().forEach( i -> System.out.println(i));

输出:

1=[1]
2=[2]
3=[2]
4=[3, 33]

3 个答案:

答案 0 :(得分:2)

你的问题有点混乱,因为你说你想要 键用于不同的值,但重复的值显然有重复的键。目前尚不清楚为什么您希望示例中值22,因为值2在源地图中出现两次,其中键2 < em>和 3

以下代码将收集重复项的所有键:

test.entrySet().stream().collect(Collectors.groupingBy(
     Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())))
  .forEach((value,keys) -> System.out.println(keys+"\t= "+value));

它将打印:

 [1]    = [1]
 [2, 3] = [2]
 [4]    = [3, 33]

为您的示例地图。如果您有选择规则,则可以从密钥列表2中选择密钥[2, 3]

答案 1 :(得分:0)

   Map<Integer, HashSet<String>> test = new TreeMap<>();
        test.put(1, new HashSet<String>());
        test.put(2, new HashSet<String>());
        test.put(3, new HashSet<String>());
        test.put(4, new HashSet<String>());

        test.get(1).add("1");
        test.get(2).add("2");
        test.get(3).add("2");
        test.get(4).add("3, 33");

    int count = 0;
    HashSet<String> distinctValues = new HashSet<>();
    test.entrySet().stream().forEach(entry -> {
      HashSet<String> entryValues = new HashSet<>();
      entryValues.addAll(entry.getValue());
      // ignore any values you've already processed
      entryValues.removeAll(distinctValues);
      if (!entryValues.isEmpty()) {
          System.out.println(++count + " = " + entryValues);
          distinctValues.addAll(entryValues);
      }
    });

答案 2 :(得分:0)

test.entrySet().stream()
        .collect(
                Collectors.toMap(
                        Map.Entry::getValue,
                        x -> x,
                        (a, b) -> a
                )
        ).values()
        .forEach(System.out::println);

修改

说明:此代码段将获取条目流并将它们放入要输入的值的映射中,同时丢弃重复项(请参阅Collectors#toMap的javadoc)。然后,它将该映射的值作为集合。结果是收集了Map.Entry::getValue不同的映射条目。

编辑2:

从你的评论中我想我明白你要做什么。您正在使用此TreeSet作为基于1的列表,并且您希望在删除重复值时折叠键。那是对的吗?也许你可以解释为什么你这样做而不只是使用列表。

Streams并不适合这种方法,所以这不会很好,但是你要去:流式传输数值,消除重复数据,收集到列表中,然后将列表转回地图

test.values().stream()
        .distinct()
        .collect(
                Collectors.collectingAndThen(
                        Collectors.toList(),
                        lst -> IntStream.range(0, lst.size()).boxed().collect(
                                Collectors.toMap(i -> i + 1, i -> lst.get(i))
                        )
                )
        ).entrySet().forEach(System.out::println);

output:
 1=[1]
 2=[2]
 3=[3, 33]