【问题标题】:Store associative array of strings with length as keys存储长度为键的字符串关联数组
【发布时间】:2012-12-19 05:20:23
【问题描述】:

我有这个输入:

5
it
your
reality
real
our

第一行是后面的字符串数。我应该以这种方式存储它(伪代码):

associative_array = [ 2 => ['it'], 3 => ['our'], 4 => ['real', 'your'], 7 => ['reality']]

如你所见,关联数组的键是存储在内部数组中的字符串的长度。 那么我怎么能在java中做到这一点?我来自php世界,所以如果你将它与php进行比较,那就很好了。

【问题讨论】:

    标签: java string collections associative-array


    【解决方案1】:
    MultiMap<Integer, String> m = new MultiHashMap<Integer, String>();
    
    for(String item : originalCollection) {
        m.put(item.length(), item);
    }
    

    【讨论】:

    • 同一个键有多个值。
    • 什么是原创收藏?
    • 这段代码使用的是 apache commons 集合库中的 MultiMap 类 - commons.apache.org/collections
    • @kirugan 这是你的原创收藏。
    【解决方案2】:

    djechlin 已经发布了一个更好的版本,但这里有一个仅使用 JDK 类的完整独立示例:

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;    
       public class Main {
            public static void main(String[] args) throws Exception{
                BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
                String firstLine = reader.readLine();
                int numOfRowsToFollow = Integer.parseInt(firstLine);
                Map<Integer,Set<String>> stringsByLength = new HashMap<>(numOfRowsToFollow); //worst-case size
                for (int i=0; i<numOfRowsToFollow; i++) {
                    String line = reader.readLine();
                    int length = line.length();
                    Set<String> alreadyUnderThatLength = stringsByLength.get(length); //int boxed to Integer
                    if (alreadyUnderThatLength==null) {
                        alreadyUnderThatLength = new HashSet<>();
                        stringsByLength.put(length, alreadyUnderThatLength);
                    }
                    alreadyUnderThatLength.add(line);
                }
                System.out.println("results: "+stringsByLength);
            }
        }
    

    它的输出如下所示:

    3
    bob
    bart
    brett
    results: {4=[bart], 5=[brett], 3=[bob]}
    

    【讨论】:

    • 为什么使用“new HashMap(numOfRowsToFollow)”?你认为它会节省内存?
    • 我认为这个解决了被问到的全部问题。我唯一的评论(尽管他没有明确地说)是他的示例按升序显示了键。我认为,您可以通过将 HashMap 更改为 TreeMap 来免费获得它。
    • @kirugan:习惯的力量。如果您不提供初始大小(因为 java 集合自己增长/缩小),它不会影响结果,但有时如果您提前知道集合将变得非常大/小,您可以节省让它增长所涉及的内存洗牌/自行收缩到那里
    • @GSP :它不排序任何东西,这就是我碰巧输入东西的方式
    • 从技术上讲,如果您要为 Hashmap 指定大小,则应使其大于实际条目数。默认情况下,Hashmap 会调整大小,而不是在您达到给定条目数时,而是当您达到某个百分比时,我认为默认值为 75%。另外,请记住,Hashmap 中的值是经过哈希处理的。如果您的 Hashmap 的大小为 5,这并不意味着 5 个条目可以整齐地放置。您几乎肯定会遇到哈希冲突破坏处理。最好留出一些空余空间以尽量减少碰撞。
    【解决方案3】:

    Java 没有关联数组。但它确实有 Hashmaps,它主要实现了相同的目标。在您的情况下,您可以为任何给定键设置多个值。因此,您可以做的是使 Hashmap 中的每个条目成为数组或某种集合。 ArrayList 是一个可能的选择。那就是:

    Hashmap<Integer,ArrayList<String>> words=new HashMap<Integer,ArrayList<String>>();
    

    我不会通过代码从文件或其他任何内容中读取您的列表,这是一个不同的问题。但只是为了让您了解结构如何工作,假设我们可以对列表进行硬编码。我们可以这样做:

    ArrayList<String> set=new ArrayList<String)();
    set.add("it");
    words.put(Integer.valueOf(2), set);
    set.clear();
    set.add("your");
    set.add("real");
    words.put(Integer.valueOf(4), set);
    

    等等

    In practice, you probably would regularly be adding words to an existing set. I often do that like this:
    
    void addWord(String word)
    {
      Integer key=Integer.valueOf(word.length());
      ArrayList<String> set=words.get(key);
      if (set==null)
      {
        set=new ArrayList<String>();
        words.put(key,set);
      }
      // either way we now have a set
      set.add(word);
    }
    

    旁注:我经常看到程序员通过将“set”放回Hashmap来结束这样的块,即“words.put(key,set)”在末尾。这是不必要的:它已经存在了。当您从 Hashmap 获得“设置”时,您获得的是参考,而不是副本,因此您所做的任何更新都只是“那里”,您不必将其放回原处。

    免责声明:此代码不在我的脑海中。没有任何明示或暗示的保证。我有一段时间没有编写任何 Java,所以我可能有语法错误或错误的函数名称。 :-)

    【讨论】:

      【解决方案4】:

      由于您的密钥似乎是小整数,您可以使用列表列表。在这种情况下,最简单的解决方案是使用 MultiMap 之类的

      Map<Integer, Set<String>> stringByLength = new LinkedHashMap<>();
      
      for(String s: strings) {
         Integer len = s.length();
         Set<String> set = stringByLength.get(s);
         if(set == null)
              stringsByLength.put(len, set = new LinkedHashSet<>());
         set.add(s);
      }
      

      【讨论】:

      • 请举个例子,你知道在 php 中没有比在 java 中那么多的集合,而且我是新手
      【解决方案5】:
      private HashMap<Integer, List<String>> map = new HashMap<Integer, List<String>>();
      
      void addStringToMap(String s) {
          int length = s.length();
          if (map.get(length) == null) {
              map.put(length, new ArrayList<String>());
          }
          map.get(length).add(s);
      }   
      

      【讨论】:

        猜你喜欢
        • 2011-06-04
        • 1970-01-01
        • 2016-07-21
        • 2019-12-17
        • 2018-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-14
        相关资源
        最近更新 更多