【问题标题】:Generate Set of Integers through HashSet using Java Streams使用 Java 流通过 HashSet 生成整数集
【发布时间】:2018-01-16 03:59:50
【问题描述】:

我试图通过获取值大于 0 的 HashMap 的所有键来创建 HashSet。为此,我考虑了 Java Streams,它带有 Collectors,但没有成功。我获得成功的唯一方法是使用带有 if 语句的 forEach 循环,如下代码所述:

HashMap<Integer, Double> profiencyOnSkill;
HashSet<Integer> skills;

profiencyOnSkill.put(1, 0.5);
profiencyOnSkill.put(2, 0.0);
profiencyOnSkill.put(3, 1.0);
profiencyOnSkill.put(4, 0.02);
profiencyOnSkill.put(5, 0.0);

profiencyOnSkill
            .entrySet()
            .stream()
            .forEach(pair -> {
                if (pair.getValue() > 0.0) {
                    skills.add(pair.getKey());
                }
            });

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

有没有直接的方法来处理收集器?我对 Collectors 的所有想法都返回了Map.Entry&lt;Integer, Double&gt;。类似的东西:

Set<Map.Entry<Integer, Double>> someSet = proficiencyOnSkill.entrySet().stream().filter(x-> x.getValue() == 2).collect(Collectors.toSet());

【问题讨论】:

  • 我试图通过获取值大于 0 的 HashMap 的所有 条目 来创建 HashSet。 你是说键吗?如果是这样,只需在收集之前添加.map(Map.Entry::getKey)
  • @shmosel 是的,正如您所指出的,正确的是键。现已编辑。

标签: java collections java-8 java-stream


【解决方案1】:

请注意,如果您之后不需要原始映射,您也可以这样做

HashMap<Integer, Double> profiencyOnSkill = …;
profiencyOnSkill.values().removeIf(v -> v<=0);
Set<Integer> skills = profiencyOnSkill.keys();

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

【讨论】:

    【解决方案2】:

    请初始化您的类型,以便您的代码可以运行。无论如何,是的,您可以在您的标准上filter,然后在Entry.keymap 并收集到Set 喜欢

    Map<Integer, Double> profiencyOnSkill = new HashMap<>();
    
    profiencyOnSkill.put(1, 0.5);
    profiencyOnSkill.put(2, 0.0);
    profiencyOnSkill.put(3, 1.0);
    profiencyOnSkill.put(4, 0.02);
    profiencyOnSkill.put(5, 0.0);
    Set<Integer> skills = profiencyOnSkill.entrySet().stream()
            .filter(pair -> pair.getValue() > 0)
            .map(Entry::getKey).collect(Collectors.toSet());
    

    您可以(但不必)只打印skills

    System.out.println(skills);
    

    我明白了

    [1, 3, 4]
    

    【讨论】:

    • 像魅力一样工作。现在出现一个问题。我在想这是否比仅遍历 HashSet 并查看是否满足条件(值大于 0)并添加到 Set 更有效。也许它们具有相同的复杂性?
    • @JoséJoaquim 复杂度相同,但(理论上)您可以将其设为parallelStream() 并获得一些额外的改进。
    【解决方案3】:
    HashMap<Integer, Double> profiencyOnSkill = new HashMap<>();
    HashSet<Integer> skills = new HashSet<>();
    
    profiencyOnSkill.put(1, 0.5);
    profiencyOnSkill.put(2, 0.0);
    profiencyOnSkill.put(3, 1.0);
    profiencyOnSkill.put(4, 0.02);
    profiencyOnSkill.put(5, 0.0);
    
    // To get both key and value
    HashSet<Entry<Integer, Double>> hs = profiencyOnSkill.entrySet().stream().filter(e -> e.getValue() > 0)
            .collect(Collectors.toCollection(HashSet::new));
    System.out.println(hs);
    
    // To get only keys
    skills = profiencyOnSkill.entrySet().stream()
        .filter(e -> e.getValue() > 0).map(Entry::getKey)
        .collect(Collectors.toCollection(HashSet::new));
    
    System.out.println(skills);
    

    【讨论】:

    • 第一个结果的替代方案:hs = new HashSet&lt;&gt;(profiencyOnSkill.entrySet()); hs.removeIf(e -&gt; e.getValue() &lt;= 0);
    【解决方案4】:

    这是一个不使用流的替代版本:

    Set<Integer> skills = new HashSet<>();
    profiencyOnSkill.forEach((k, v) -> { if (v > 0.0) skills.add(k); });
    

    这不过是原始代码的改进版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-30
      • 1970-01-01
      • 2016-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多