如何遍历Guava multimap以成对的形式输出值?



对于Guava Multimap中的每个键,我需要获取相应的值并与它们组成不依赖于顺序的成对。对的唯一性不依赖于键内的make对的顺序。[a, b] = [b, a]。如果在另一个密钥中找到[B,A]对,则应将其视为另一对。我不知道如何迭代这些值,所以我可以打印出不依赖于顺序的对。我也不知道如何索引这个。对于数组,我可以使用双循环。

下面是一个示例Multimap:

BE0004429: [DB00515, DB00951, DB01582]
BE0000059: [DB00603, DB01285]
BE0001052: [DB00366, DB00472, DB00856, DB01104, DB01149]

我想把这些数据改成这种格式。仔细看,我正试着取每个键的值并使其成对。

我想取每个键中的第一个值,并将其与其他值配对。取第二个值并将其与后面的值配对。直到没有唯一的对。

DB00515, DB00951
DB00515, DB01582
DB01582, DB00951
DB00603, DB01285
DB00366, DB00472
DB00366, DB00856
DB00366, DB01104
DB00366, DB01149
DB00472, DB00856
DB00472, DB01104
DB00472, DB01149
DB00856, DB01104
DB00856, DB01149
DB01104, DB01149

我在问题更新之前写了这个答案,以便更清楚地描述期望的行为,但是我怀疑这个答案仍然会帮助一些偶然发现这个问题的人试图理解迭代Multimap的不同方法,所以我在这里留下这个答案留给后代。


假设我们从以下Multimap开始:

Multimap<String, Integer> map = new ImmutableSetMultimap.Builder<String, Integer>()
                                .put("one", 1)
                                .putAll("several", 1, 2, 3)
                                .putAll("many", 1, 2, 3, 4, 5)
                                .build();

我们可以用几种方式打印它的内容,让我们试试:

  1. 作为原始字符串:

     map.toString()
    
    {one=[1], several=[1, 2, 3], many=[1, 2, 3, 4, 5]}
    
  2. 作为集合键=>具有唯一键的集合对:

     for(String key : map.keySet()) {
       System.out.println(key+": "+map.get(key));
     }
     // OR with the asMap() view
     for(Entry<String,Collection<Integer> e : map.asMap().entrySet()) {
       System.out.println(e.getKey()+": "+e.getValue());
     }
    
    one: [1]
    
     several: [1, 2, 3]
     many: [1, 2, 3, 4, 5]
    
  3. 作为集合键=>值对,具有重复的键(如果是ListMultimap,可能还有值):

     for(Entry<String, Integer> e : map.entries()) {
       System.out.println(e.getKey()+": "+e.getValue());
     }
    
    one: 1
    
     several: 1
     several: 2
     several: 3
     many: 1
     many: 2
     many: 3
     many: 4
     many: 5
    
  4. 作为值的集合,不关心它们的键:

     for(Integer v : map.values()) {
       System.out.println(v);
     }
    
    1
    
     1
     2
     3
     1
     2
     3
     4
     5
    

这些通常是使用Multimap的方式。你说你试图"打印"出不依赖于顺序的对。-我不清楚这是什么意思,但如果你说你想要选项3的输出是在一个任意的顺序,你可以把你的字符串写到一个列表,然后洗牌,像这样:

List<String> pairs = new ArrayList<>();
for(Entry<String, Integer> e : map.entries()) {
  pairs.add(e.getKey()+": "+e.getValue());
}
Collections.shuffle(pairs);
for(String s : pairs) {
  System.out.println(s);
}

这将以任意顺序成对地打印Multimap的内容

这个问题有两个部分,现在我明白了,你正在使用Multimaps这一事实并不是很重要。尝试将问题分解成各个组成部分是很有价值的;当你这样做的时候,问题往往会变得更清晰,甚至看起来微不足道。

  1. 如何从集合中打印连续的对?

    我们需要定义一个函数,该函数将接受一个Collection(这将允许我们使用任意Multimaps),并生成您的pair:

    public static <V> List<String> genPairs(Collection<V> col) {
      List<V> ls = ImmutableList.copyOf(col);
      List<String> ret = new ArrayList<>();
      for (int i = 0; i < ls.size()-1; i++) {
        for (int j = i+1; j < ls.size(); j++) {
          ret.add(ls.get(i)+", "+ls.get(j));
        }
      }
      return ret;
    }
    
    演示:

    for(String pair : genPairs(ImmutableList.of(1,2,3))) {
      System.out.println(pair);
    }
    
    1, 2
    1, 3
    2, 3
    
  2. 如何从Multimap的值中打印连续的对?

    这部分很简单,只需遍历值集合并调用上面的函数:

    for(Collection<String> col : multimap.asMap().values()) {
      for(String pair : genPairs(col)) {
        System.out.println(pair);
      }
      System.out.println();
    }
    

希望这对你有帮助。

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class GuavaSample {
    public static void main(String[] args) {
        Multimap<String, String> multiMap = ArrayListMultimap.create();
        multiMap.put("BE0004429", "DB00515");
        multiMap.put("BE0004429", "DB00951");
        multiMap.put("BE0004429", "DB01582");
        multiMap.put("BE0000059", "DB00603");
        multiMap.put("BE0000059", "DB01285");
        multiMap.put("BE0001052", "DB00366");
        multiMap.put("BE0001052", "DB00472");
        multiMap.put("BE0001052", "DB00856");
        multiMap.put("BE0001052", "DB01104");
        multiMap.put("BE0001052", "DB01149");
        for (String key : multiMap.keySet()) {
            List<String> list = (List<String>) multiMap.get(key);
            for (int i = 0; i < list.size(); i++) {
                for (int j = i + 1; j < list.size(); j++) {
                    System.out.println(list.get(i) + "," + list.get(j));
                }
            }
            System.out.println();
        }
    }
}