【问题标题】:Find the most common String in ArrayList()在 ArrayList() 中查找最常见的字符串
【发布时间】:2014-05-24 06:20:18
【问题描述】:

有没有办法在ArrayList 中找到最常见的String

ArrayList<String> list = new ArrayList<>();
list.add("test");
list.add("test");
list.add("hello");
list.add("test");

应该从这个列表中找到单词“test”["test","test","hello","test"]

【问题讨论】:

标签: java arrays list arraylist


【解决方案1】:

不要重新发明轮子,使用Collections类的frequency方法:

public static int frequency(Collection<?> c, Object o)

返回指定集合中的元素个数等于 指定的对象。更正式地,返回元素的数量 e 在集合中使得 (o == null ? e == null : o.equals(e))。

如果您需要计算所有元素的出现次数,请巧妙地使用 Map 和循环 :) 或者将您的列表放入一个 Set 中,并使用上面的 frequency 方法在该集合的每个元素上循环。高温

编辑/Java 8:如果您想要一个功能更强大的 Java 8 单行 lambda 解决方案,请尝试:

Map<String, Long> occurrences = 
  list.stream().collect(Collectors.groupingBy(w -> w, Collectors.counting()));

【讨论】:

  • w-&gt;w代替Function.identity()
  • 这不会返回每个字符串中每个单词的频率。它返回最常出现的字符串。我如何调整它以返回出现在字符串 ArrayList 中的最频繁的单词
  • @Cemo 我个人觉得w -&gt; w 用一种更简洁不会造成太大伤害的语言来减少冗长。有什么支持Function.identity()的有力论据?
【解决方案2】:

In statistics, this is called the "mode"。一个普通的 Java 8 解决方案如下所示:

Stream.of("test","test","hello","test")
      .collect(Collectors.groupingBy(s -> s, Collectors.counting()))
      .entrySet()
      .stream()
      .max(Comparator.comparing(Entry::getValue))
      .ifPresent(System.out::println);

产量:

test=3

jOOλ 是一个在流上支持mode() 的库。以下程序:

System.out.println(
    Seq.of("test","test","hello","test")
       .mode()
);

产量:

Optional[test]

(免责声明:我为 jOOλ 背后的公司工作)

【讨论】:

    【解决方案3】:

    根据问题,具体来说只是为了获取单词,而不是次数(即键的值)。

    String mostRepeatedWord 
        = list.stream()
              .collect(Collectors.groupingBy(w -> w, Collectors.counting()))
              .entrySet()
              .stream()
              .max(Comparator.comparing(Entry::getValue))
              .get()
              .getKey();
    

    【讨论】:

      【解决方案4】:

      您可以创建HashMap&lt;String,Integer&gt;。如果字符串已经出现在地图中,则将其 key 加一,否则,将其添加到地图中。

      例如:

      put("someValue", 1);
      

      然后,假设它再次是“someValue”,你可以这样做:

      put("someValue", get("someValue") + 1);
      

      既然“someValue”的key是1,那么现在你放它的时候,key就是2了。

      之后,您可以轻松地遍历地图并提取具有最高 valuekey

      我没有写一个完整的解决方案,尝试构建一个,如果你有问题在另一个问题中发布。最好的做法是自学。

      【讨论】:

      • 提示:使用yourMap.compute("someValue", (k, counter) -&gt; counter == null ? 0 : counter + 1) 插入地图!
      【解决方案5】:

      我认为最好的方法是使用包含计数的地图。

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

      然后遍历你的数组填充这张地图:

      for(String s: list)
      {
        Integer c = stringsCount.get(s);
        if(c == null) c = new Integer(0);
        c++;
        stringsCount.put(s,c);
      }
      

      最后,您可以获得在地图上重复次数最多的元素:

      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 string: " + mostRepeated.getKey());
      

      【讨论】:

        【解决方案6】:

        您可以使用HashMap&lt;String,Integer&gt;。遍历数组,你可以检查每个String是否还不是HashMap的Key,添加它并将值设置为1,如果是,则将其值增加1。

        然后你有一个HashMap,其中包含所有唯一的Strings 和一个关联的数字,说明它们在数组中的数量。

        【讨论】:

          【解决方案7】:

          如果有人需要从通常的 String[] 数组中找到最流行的(使用列表):

          public String findPopular (String[] array) {
              List<String> list = Arrays.asList(array);
              Map<String, Integer> stringsCount = new HashMap<String, Integer>();
              for(String string: list)
              {
                  if (string.length() > 0) {
                      string = string.toLowerCase();
                      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;
              }
              try {
                  return mostRepeated.getKey();
              } catch (NullPointerException e) {
                  System.out.println("Cannot find most popular value at the List. Maybe all strings are empty");
                  return "";
              }
          
          }
          
          • 不区分大小写

          【讨论】:

            【解决方案8】:

            我知道这需要更多时间来实现,但您可以通过在节点中存储计数和字符串信息来使用堆数据结构

            【讨论】:

              【解决方案9】:

              你可以使用 Guava 的 Multiset:

              ArrayList<String> names = ...
              
              // count names 
              HashMultiset<String> namesCounts = HashMultiset.create(names);
              Set<Multiset.Entry<String>> namesAndCounts = namesCounts.entrySet();
              
              // find one most common
              Multiset.Entry<String> maxNameByCount = Collections.max(namesAndCounts, Comparator.comparing(Multiset.Entry::getCount));
              
              // pick all with the same number of occurrences
              List<String> mostCommonNames = new ArrayList<>();
              for (Multiset.Entry<String> nameAndCount : namesAndCounts) {
                  if (nameAndCount.getCount() == maxNameByCount.getCount()) {
                      mostCommonNames.add(nameAndCount.getElement());
                  }
              }
              

              【讨论】:

                【解决方案10】:
                import java.util.ArrayList;
                import java.util.Arrays;
                import java.util.Collections;
                import java.util.HashMap;
                import java.util.Map;
                

                公共类 StringChecker {

                public static void main(String[] args) {
                ArrayList<String> string;
                string = new ArrayList<>(Arrays.asList("Mah", "Bob", "mah", "bat", "MAh", "BOb"));
                Map<String, Integer> wordMap = new HashMap<String, Integer>();
                
                for (String st : string) {
                    String input = st.toUpperCase();
                    if (wordMap.get(input) != null) {
                        Integer count = wordMap.get(input) + 1;
                        wordMap.put(input, count);
                    } else {
                        wordMap.put(input, 1);
                    }
                }
                System.out.println(wordMap);
                Object maxEntry = Collections.max(wordMap.entrySet(), Map.Entry.comparingByValue()).getKey();
                System.out.println("maxEntry = " + maxEntry);
                

                }

                【讨论】:

                  【解决方案11】:

                  使用此方法,如果您的 ArrayList 中有多个最常见的元素,您可以通过将它们添加到新的 ArrayList 来取回所有元素。

                  public static void main(String[] args) {
                  
                   List <String> words = new ArrayList<>() ; 
                  
                  words.add("cat") ; 
                  words.add("dog") ; 
                  words.add("egg") ; 
                  words.add("chair") ; 
                  words.add("chair") ; 
                  words.add("chair") ; 
                  words.add("dog") ; 
                  words.add("dog") ;  
                  
                  Map<String,Integer> count = new HashMap<>() ; 
                  
                      for (String word : words) {  /* Counts the quantity of each 
                                                        element */
                          if (! count.containsKey(word)) {             
                              count.put(word, 1 ) ; 
                          }
                  
                          else {
                              int value = count.get(word) ; 
                              value++ ; 
                  
                              count.put(word, value) ;
                          }       
                      }
                  
                      List <String> mostCommons = new ArrayList<>() ; /* Max elements  */
                  
                      for ( Map.Entry<String,Integer> e : count.entrySet() ) {
                  
                          if (e.getValue() == Collections.max(count.values() )){
                                              /* The max value of count  */
                  
                              mostCommons.add(e.getKey()) ;
                          }   
                      }
                  
                      System.out.println(mostCommons);
                  
                   }
                  
                  }
                  

                  【讨论】:

                    【解决方案12】:

                    有很多答案建议使用 HashMaps。我真的不喜欢它们,因为无论如何你都必须再次遍历它们。相反,我会对列表进行排序

                    Collections.sort(list);
                    

                    然后循环遍历它。类似于

                    String prev = null, mostCommon=null;
                    int num = 0, max = 0;
                    for (String str:list) {
                      if (str.equals(prev)) {
                        num++;
                      } else {
                        if (num>max) {
                          max = num;
                          mostCommon = str;
                        }
                        num = 1;
                        prev = str;
                      }
                    }
                    

                    应该这样做。

                    【讨论】:

                    • “我真的不喜欢它们” ... 对一组值进行两次迭代仍然是O(N) 的复杂性。您的算法使用排序,这是O(N log N) 复杂度,这肯定更糟。
                    • 我同意 Bex 的观点。在我看来,排序实际上并不是一个坏主意。它很容易实现并且具有 O(nlogn) 时间复杂度和 O(1) 空间。虽然使用 hashmap 和 priorityqueue 具有 O(nlogn) 时间复杂度和 O(n) 空间。由于插入到 pq 是 O(logn),迭代 Hashmap 的条目并将它们插入到 pq 是 O(nlogn) 在最坏的情况下。如果我错了纠正我。 docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
                    猜你喜欢
                    • 2017-03-30
                    • 2020-02-23
                    • 1970-01-01
                    • 2012-12-08
                    • 2014-12-14
                    • 2011-02-03
                    • 2015-11-29
                    • 2020-03-20
                    • 1970-01-01
                    相关资源
                    最近更新 更多