【问题标题】:Using Java 8 Stream to replace for loop and populate a Map使用 Java 8 Stream 替换 for 循环并填充 Map
【发布时间】:2019-03-20 12:13:10
【问题描述】:

在这个 java 赋值中,我们有一个 for 循环,它读取我们在这个程序中使用的文本文件,我们应该用流替换它。这是程序的一部分以及我们应该替换的内容:

    import java.io.FileNotFoundException;
    import java.util.List;
    import java.util.Map;
    import java.util.TreeMap;


    public class FrequentWords {

    public static void main(String[] args) throws FileNotFoundException {

    String filename = "SophieSallyJack.txt";
    if (args.length == 1) {
        filename = args[0];
    }
    Map<String, Integer> wordFrequency = new TreeMap<>();

    List<String> incoming = Utilities.readAFile(filename);

    // TODO replace the following loop with a single statement using streams    
    // that populates wordFrequency         
    for (String word : incoming) {
        word = word.toLowerCase();
        if (!"".equals(word.trim())) {
            Integer cnt = wordFrequency.get(word);
            if (cnt == null) {
                wordFrequency.put(word, 1);
            } else {
                int icnt = cnt + 1;
                wordFrequency.put(word, icnt);
            }
        }
    }

我已经尝试过了,但我似乎无法弄清楚其他任何事情:

incoming.stream()
        .collect(Collectors.toMap(word -> word, word -> 1, Integer::sum)).entrySet();

【问题讨论】:

  • 不确定为什么 wordFrequency = incoming.stream() .map(String::toLowerCase).filter(word -&gt; !word.trim().isEmpty()) .collect(Collectors.toMap(Function.identity(), word -&gt; 1, Integer::sum)) 不适合您,假设您知道 entrySet()Set 而不能分配给 Map

标签: java file loops filter java-stream


【解决方案1】:

您可以尝试以下方法:

wordFrequency = incoming.stream()
               .map(String::toLowerCase).filter(word -> !word.trim().isEmpty())
               .collect(Collectors.toMap
                (word -> word, word -> 1, (a, b) -> a + b, TreeMap::new));

您错过了BinaryOperator,它将合并key 的值已经存在Collectors.toMap()

【讨论】:

  • 小建议word -&gt; wordFunction.identity()
  • 您可以使用(a, b) -&gt; a + b,而不是Integer::sum
【解决方案2】:

作为替代方案,您可以简单地使用:

wordFrequency = incoming.stream()
                        .map(String::toLowerCase)  // only if you're planning to store in lowercase or else move this to filtering predicate
                        .filter(word -> !word.trim().isEmpty())
                        .collect(Collectors.toMap(Function.identity(), 
                                                       word -> 1, Integer::sum));

考虑到您知道entrySet()Set,而不是像问题中那样无论如何都不能分配给Map

【讨论】:

    【解决方案3】:
    private static Map<String,Integer> toMapFunction(Collection< ? extends String> collection){
            return collection.stream().map(String::toLowerCase)
                    .filter(str -> !str.trim().isEmpty())
                    .collect(Collectors.toMap(Function.identity(), value -> 1, (oldValue, newValue) -> oldValue + newValue, TreeMap::new));
        }
    
        public static void main(String[] args) {
            List<String> stringList = Arrays.asList("joy", "joy", "lobo", "lobo", "lobo", "joy", "joy", "joy", "david", "hibbs");
            System.out.println(toMapFunction(stringList));
        }
    

    这将是程序的输出:

    {david=1, hibbs=1, joy=5, lobo=3}
    

    【讨论】:

      猜你喜欢
      • 2022-10-13
      • 1970-01-01
      • 2022-11-13
      • 2020-07-18
      • 1970-01-01
      • 2018-09-17
      • 1970-01-01
      • 1970-01-01
      • 2018-12-27
      相关资源
      最近更新 更多