【问题标题】:How to for each the hashmap? [duplicate]如何为每个哈希图? [复制]
【发布时间】:2023-04-10 00:50:01
【问题描述】:

我有这个字段:

HashMap<String, HashMap> selects = new HashMap<String, HashMap>();

对于每个Hash&lt;String, HashMap&gt;,我需要创建一个ComboBox,其项是HashMap &lt;String, **HashMap**&gt; 的值(恰好是HashMap 本身)。

通过(非功能性)演示:

for (int i=0; i < selects.size(); i++) {
    HashMap h = selects[i].getValue();
    ComboBox cb = new ComboBox();

    for (int y=0; y < h.size(); i++) {
        cb.items.add(h[y].getValue);
    }
}

【问题讨论】:

标签: java


【解决方案1】:

我知道我有点晚了,但我也会分享我所做的,以防它帮助其他人:

HashMap<String, HashMap> selects = new HashMap<String, HashMap>();

for(Map.Entry<String, HashMap> entry : selects.entrySet()) {
    String key = entry.getKey();
    HashMap value = entry.getValue();

    // do what you have to do here
    // In your case, another loop.
}

【讨论】:

  • 我不记得如何写这个,所以我总是回到同样的答案。赞成,因为这是一个干净的答案,并且这段代码被复制粘贴到我项目中的很多地方,谢谢!
  • @Katu 只需编写 yourmap..entrySet().for IDE 自动完成功能就会处理它。
【解决方案2】:

Lambda 表达式 Java 8

在 Java 1.8 (Java 8) 中,通过使用类似于 Iterable 中的迭代器的聚合操作(流操作)中的 forEach 方法,这变得容易多了 界面。

只需将下面的语句复制粘贴到您的代码中,并将 HashMap 变量从 hm 重命名为您的 HashMap 变量即可打印出键值对。

HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
 *     Logic to put the Key,Value pair in your HashMap hm
 */

// Print the key value pair in one line.
hm.forEach((k,v) -> System.out.println("key: "+k+" value:"+v));

这是一个使用 Lambda 表达式 的示例:

    HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
    Random rand = new Random(47);
    int i=0;
    while(i<5){
        i++;
        int key = rand.nextInt(20);
        int value = rand.nextInt(50);
        System.out.println("Inserting key: "+key+" Value: "+value);
        Integer imap =hm.put(key,value);
        if( imap == null){
            System.out.println("Inserted");
        }
        else{
            System.out.println("Replaced with "+imap);
        }               
    }

    hm.forEach((k,v) -> System.out.println("key: "+k+" value:"+v));

Output:

Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11

同样可以使用 Spliterator

Spliterator sit = hm.entrySet().spliterator();

更新


包括指向 Oracle Docs 的文档链接。 有关 Lambda 的更多信息,请访问此 link,并且必须阅读 Aggregate Operations,对于 Spliterator,请访问此 link

【讨论】:

  • 我猜我们不能在封闭范围内的局部变量不声明它们是最终的。使用在 lambda 主体外部声明的变量时得到 Local variable schedule defined in an enclosing scope must be final or effectively final,这与 groovy 中的闭包不同。
  • 使用 lambdas 的缺点是您不能在 lambda 内返回其他方法。
  • 这里的分离器有什么用?你在使用并行流吗?
【解决方案3】:

Map.values():

HashMap<String, HashMap<SomeInnerKeyType, String>> selects =
    new HashMap<String, HashMap<SomeInnerKeyType, String>>();

...

for(HashMap<SomeInnerKeyType, String> h : selects.values())
{
   ComboBox cb = new ComboBox();
   for(String s : h.values())
   {
      cb.items.add(s);
   }
}

【讨论】:

  • +1:这是比我的答案更简洁的方法(假设我们使用的是 Java 5 或更高版本)
  • 在外部 HashMap 上使用通用参数似乎表明 Java 5 或更高版本。 [[ 但我确实想知道这是什么 Java,因为内部 HashMap 没有通用参数,并且在 HashMap 上完成了数组访问......但它只是一些用于传达问题的“伪”代码。 ]]
  • 想解释一下为什么它似乎对您不起作用?您使用的是 Java 5 还是更高版本?我们正在关注您的代码示例,该示例在组合框创建后似乎没有任何作用。还是这些值不是您想要的顺序?还是您需要键而不是组合框中的值?我认为大多数人都同意到目前为止 3 个答案中的任何一个都应该可以正常工作,因此如果您向我们提供更多信息,我们可能会在其他地方应用答案或其他问题。
  • ooohh...我愚蠢=)。只有一个问题如何获得 HashMapString, HashMap>
  • @simply denis - 恐怕我不明白你的问题?您是在问如何获得对HashMap&lt;String, HashMap&lt;SomeInnerKeyType, String&gt;&gt; 的引用?如果您的循环在一个方法中,您应该能够使用this.selects 或简单地使用selects?否则,您应该将映射作为参数传递给包含循环的方法。或者您是在问如何为给定键获取特定的内部HashMap&lt;SomeInnerKeyType, String&gt;this-&gt;String?)您将使用selects.get(keyString)。如果我完全误解了,请澄清。
【解决方案4】:

流 Java 8

除了接受lambda expressionforEach 方法外,我们还在Java 8 中获得了stream API。

迭代条目(使用 forEach 和 Streams):

sample.forEach((k,v) -> System.out.println(k + "=" + v)); 
sample.entrySet().stream().forEachOrdered((entry) -> {
            Object currentKey = entry.getKey();
            Object currentValue = entry.getValue();
            System.out.println(currentKey + "=" + currentValue);
        });
sample.entrySet().parallelStream().forEach((entry) -> {
            Object currentKey = entry.getKey();
            Object currentValue = entry.getValue();
            System.out.println(currentKey + "=" + currentValue);
        });

流的优点是它们可以轻松并行化,并且在我们拥有多个 CPU 时非常有用。我们只需要使用parallelStream() 代替上面的stream()。对于并行流,使用forEach 更有意义,因为forEachOrdered 对性能没有影响。如果我们想遍历键,我们可以使用sample.keySet() 和值sample.values()

为什么 forEachOrdered 而不是 forEach 带有流?

流也提供forEach 方法,但forEach 的行为是明确的不确定性,因为forEachOrdered 会按照流的遇到顺序为此流的每个元素执行操作如果流具有定义的遇到顺序。所以forEach 不保证订单会被保留。另请查看this 了解更多信息。

【讨论】:

    【解决方案5】:

    您可以使用迭代器迭代 HashMap(和许多其他集合),例如:

    HashMap<T,U> map = new HashMap<T,U>();
    
    ...
    
    Iterator it = map.values().iterator();
    
    while (it.hasNext()) {
        System.out.println(it.next());
    }
    

    【讨论】:

    • 我无法将这样的设计降到下面的水平
    • @是的,你可以。你可以基于it.next()创建一个内部迭代器。
    【解决方案6】:

    我一般和cx42net一样,但是我没有显式创建Entry。

    HashMap<String, HashMap> selects = new HashMap<String, HashMap>();
    for (String key : selects.keySet())
    {
        HashMap<innerKey, String> boxHolder = selects.get(key);
        ComboBox cb = new ComboBox();
        for (InnerKey innerKey : boxHolder.keySet())
        {
            cb.items.add(boxHolder.get(innerKey));
        }
    }
    

    这对我来说似乎是最直观的,我认为我对迭代地图的值有偏见。

    【讨论】:

      【解决方案7】:

      使用entrySet

      /**
       *Output: 
      D: 99.22
      A: 3434.34
      C: 1378.0
      B: 123.22
      E: -19.08
      
      B's new balance: 1123.22
       */
      
      import java.util.HashMap;
      import java.util.Map;
      import java.util.Set;
      
      public class MainClass {
        public static void main(String args[]) {
      
          HashMap<String, Double> hm = new HashMap<String, Double>();
      
          hm.put("A", new Double(3434.34));
          hm.put("B", new Double(123.22));
          hm.put("C", new Double(1378.00));
          hm.put("D", new Double(99.22));
          hm.put("E", new Double(-19.08));
      
          Set<Map.Entry<String, Double>> set = hm.entrySet();
      
          for (Map.Entry<String, Double> me : set) {
            System.out.print(me.getKey() + ": ");
            System.out.println(me.getValue());
          }
      
          System.out.println();
      
          double balance = hm.get("B");
          hm.put("B", balance + 1000);
      
          System.out.println("B's new balance: " + hm.get("B"));
        }
      }
      

      在此处查看完整示例:

      【讨论】:

      • 它确实有效,我每天都在使用它 :) 到底什么不起作用?正如您拥有HashMap&lt;String, HashMap&gt; 一样,您将需要两个循环——一个用于外部HashMap,一个用于内部HashMap。顺便说一句 - 你应该明确地输入第二个 HashMap - 不知道你在其中存储了什么,但是像 HashMap> 这样的东西 - 但是,从你的例子来看,你似乎应该使用HashMap&lt;String, Set&lt;String&gt;&gt;。还有一件事——尽可能使用接口:Map&lt;String, Map&gt;
      猜你喜欢
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-08
      • 2012-07-17
      • 2011-07-16
      相关资源
      最近更新 更多