【问题标题】:Find most common String(s) in an ArrayList在 ArrayList 中查找最常见的字符串
【发布时间】:2017-03-30 14:14:48
【问题描述】:

我的问题有点不同。我有一个包含一些路由的 ArrayList。例如:

[ACD, CDE, DEB, EBJ, BJK, JKO, ACD, CDE, DEX, EXB, XBJ, BJK, JKO, KOL]

当我使用 HashMap 进行计数时,它只打印一个字符串:

Most common route: ACD
This route repeats 2 times.

没错,但是字符串 CDE、BJK 和 JKO 也重复了 2 次。由于我是编程初学者,请您告诉我我必须在代码中更改哪些内容,以便打印所有最常见的路线(字符串)。
代码如下:

Map<String, Integer> stringsCount = new HashMap<>();

    for(String string: listaRuta)
    {
      Integer count = stringsCount.get(string);
      if(count == null) count = new Integer(0);
      count++;
      stringsCount.put(string,count);
    }

    Map.Entry<String,Integer> mostRepeated = null;
    for(Map.Entry<String, Integer> e: stringsCount.entrySet())
    {
        if(mostRepeated == null || mostRepeated.getValue()<e.getValue())
            mostRepeated = e;
    }
    if(mostRepeated != null)
        System.out.println("Most common route: " + mostRepeated.getKey());
        System.out.println("This route repeats " + mostRepeated.getValue() + " times.");

【问题讨论】:

标签: java string list arraylist hashmap


【解决方案1】:

这是使用来自Eclipse CollectionsBagtopOccurrences 的解决方案。

MutableList<String> list =
        Lists.mutable.with("ACD", "CDE", "DEB", "EBJ", "BJK", "JKO", 
                "ACD", "CDE", "DEX", "EXB", "XBJ", "BJK", "JKO", "KOL");
MutableList<ObjectIntPair<String>> pairs =
        list.toBag().topOccurrences(1);
System.out.println(pairs);

输出:

[BJK:2, JKO:2, ACD:2, CDE:2]

Bag 类似于Map&lt;Key, Integer&gt;,其中的值是键的计数。在外部,Bag 的接口类似于Collection&lt;Key&gt;。 Eclipse Collections 具有原始集合,因此 HashBag 实现在内部使用ObjectIntHashMap 来提高效率。

Bag 上的方法topOccurrences 具有处理平局的逻辑,这就是为什么在结果List 中返回多个ObjectIntPair

注意:我是 Eclipse Collections 的提交者。

【讨论】:

    【解决方案2】:

    另外,我更喜欢使用 Lamba 解决方案来构建 hasmap。一旦你有了地图,这就是你的目标的常见用途:

    int maxValue=(Collections.max(stringsCount.values()));  // This will return max value in the Hashmap
    for (Entry<String, Integer> entry : stringsCount.entrySet()) {  // Iterate through the hashmap
        if (entry.getValue()==maxValue) {
            System.out.println(entry.getKey());     // Print the key with max value
        }
    }
    

    或者以更紧凑的方式使用 java 8 流和 Lamba:

    long maxValue=(Collections.max(stringsCount.values()));
    stringsCount.entrySet()
         .stream()
         .filter(s -> s.getValue() == maxValue).forEach(System.out::println);
    

    【讨论】:

      【解决方案3】:
      package de.ninjaneers;
      
      import java.util.Arrays;
      import java.util.Map;
      import java.util.Objects;
      import java.util.stream.Collectors;
      
      public class Main {
      
          public static void main(String[] args) {
      
              String[] entries = {"ABC", "ABC", "DEF", "DEF", "DD", "MM"};
              Map<String, Long> counts = Arrays.stream(entries)
                      .collect(Collectors.groupingBy(e -> e, Collectors.counting()));
              Long max = counts.entrySet().stream()
                      .map(Map.Entry::getValue)
                      .max(Long::compare)
                      .orElse(0L);
              Map<String, Long> onlyTheMax = counts.entrySet().stream()
                      .filter(e -> Objects.equals(max, e.getValue()))
                      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
      
          }
      }
      

      首先计算所有条目,然后获得最大值,最后过滤掉所有小于最大值的条目。对不起,第一个简短的例子。

      【讨论】:

      • 这会正确构建 hasmap,但不会按照 OP 的要求提供原始列表中最常见的字符串。
      • 在这种情况下,它显示 BJK 是最常见的,有 4 次重复。这是不正确的。 @Christoph Grimmer-Dietrich
      • @szentmihaly 在这个答案中有一种不同的方法来构建带有字符串和计数器的哈希图(您也正确地构建了地图)。没有实现如何找到原始列表中最常见的字符串。
      • @user6904265 你说得对,我的回答很简短。
      【解决方案4】:

      没有 Streams 和 Lambdas 的解决方案(初学者更容易理解):

      测试类

      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      public class Counter {
      
          public static void main(String[] args) {
          List<String> test = new ArrayList<>();
          test.add("a");
          test.add("b");
          test.add("b");
          test.add("c");
          test.add("c");
          test.add("c");
      
          Map<String, Integer> stringsCount = new HashMap<>();
      
          for (String s : test) {
              if (stringsCount.get(s) == null) {
              stringsCount.put(s, 1);
              } else {
              stringsCount.replace(s, stringsCount.get(s) + 1);
              }
          }
      
              for (Map.Entry entry : stringsCount.entrySet()) {
                  System.out.println(entry.getKey() + ", " + entry.getValue());
              }
          }
      }
      

      输出

      一个,1 乙,2 三、3

      【讨论】:

        猜你喜欢
        • 2014-05-24
        • 2020-02-23
        • 1970-01-01
        • 2012-12-08
        • 2014-12-14
        • 2011-02-03
        • 2015-11-29
        • 2020-03-20
        • 1970-01-01
        相关资源
        最近更新 更多