【问题标题】:Multimap guava values多图番石榴值
【发布时间】:2017-03-06 09:54:43
【问题描述】:

我有这种情况:

ID={1,2,3}
Title ={T1,T2,T3} 
Place ={P1,P2,P3}

我想要这个结果:

ID: 1 , Title: T1, Place: P1
ID: 2 , Title: T2, Place: P2
ID: 3 , Title: T3, Place: P3

我使用 Multimap (Guava) 来存储 ID 和标题及其多个值:

Multimap<String, String> MultiMap = ArrayListMultimap.create();

但是,到目前为止,我无法获得如上所述的预期结果。我尝试使用此代码:

   for (Entry<String, String> key : MultiMap.entries()) 
    {
      System.out.println("name : " + key.getKey() + " value : " + key.getValue());
    }

但是,使用这段代码,我得到的结果是这样的:

name : ID value: 1
name : ID value: 2
name : ID value: 3 
name : Title value: T1
name : Title value: T2
name : Title value: T3
name : Place value: P1
name : Place value: P2
name : Place value: P3

如何使用 Multimap 获得如上所述的结果?

【问题讨论】:

  • 您可能想要Map&lt;Integer, String&gt;,其中键(ID)映射到标题,而不是Multimap&lt;String, String&gt;。只需将您的数据存储在地图中并使用System.out.println("ID: " + entry.getKey() + " Title: " + entry.getValue()); 打印即可。
  • 这不是问题所在。在我的问题中,可以将多个值分配给一个 id 或任何值,例如,可以将标题、地点等分配给 ID1
  • 也许您可以创建一个同时包含标题和地点的对象(例如 IdData),然后使用地图?这不一定能解决您的问题,但可能是另一种解决方案。

标签: java indexing guava multimap


【解决方案1】:

我认为您没有正确理解 Multimap 是什么。 Multimap 从一个或多个键映射到多个值,它是一种 n 到 m 的关系。您似乎拥有的是从 ID 到 Title 的关系,这是一个 n 对 1 的关系。正确的数据结构是 Map,而不是 Multimap。

Map<Integer, String> titlesById = new TreeMap<>(); // keep map ordered by ID
titlesById.put(1, "T1");
titlesById.put(2, "T2");
titlesById.put(3, "T3");
for(Map.Entry<Integer, String> entry : titlesById.entrySet()){
  System.out.println("ID : " + entry.getKey() + " Title : " + entry.getValue());
}

这应该会产生所需的输出。

注意:如果您可能通过 ID 从 Map 中查找标题,那么您可能希望从 TreeMap 切换到 HashMap,因为 HashMap 具有恒定时间查找。


更新:显然你确实需要一个 Multimap。然后把上面的代码改成这样:

Multimap<Integer, String> titlesById = TreeMultimap.create<>(); // keep map ordered by ID
titlesById.putAll(1, Arrays.asList("T1a", "T1b", "T1c"));
titlesById.putAll(2, Arrays.asList("T2a", "T2b"));
titlesById.put(3, "T3");
for(Map.Entry<Integer, String> entry : titlesById.entries()){
  System.out.println("ID : " + entry.getKey() + " Title : " + entry.getValue());
}

再次重申:TreeMultimap 按键对 Map 进行排序,HashMultimap 具有高效查找功能。


它变得越来越有趣,现在您希望将 3 个值相互连接。在这种情况下,您应该使用Table(3 维地图)。例如

Table<Integer, String, String> titlesAndPlacesById = TreeBasedTable.create();
titlesAndPlacesById.put(1, "T1", "P1");
titlesAndPlacesById.put(2, "T2", "P2");
titlesAndPlacesById.put(3, "T3", "P3");

for(Table.Cell<Integer, String, String> cell : titlesAndPlacesById.cellSet()){
  System.out.println("ID : " + cell.getColumnKey() + " Title : " + cell.getRowKey() + ", Place: " + cell.getValue());
}

但这不是一个完美的匹配。如果您想将 ID 映射到标题和地点,那么您可能需要一个自定义对象来封装标题和地点,并将其用作从整数到自定义类型的普通旧 Map 中的值。

public class TitleAndPlace{
    private final String title;
    private final String place;

    TitleAndPlace(String title, String place) {
        this.title = title;
        this.place = place;
    }

    public String getTitle() { return title; }

    public String getPlace() { return place; }

    @Override public boolean equals(Object o) {
        if (this == o) return true;
        else if (o instanceof TitleAndPlace) {
            TitleAndPlace that = (TitleAndPlace) o;
            return Objects.equals(title, that.title)
                && Objects.equals(place, that.place);
        } else return false;
    }

    @Override public int hashCode() {
        return Objects.hash(title, place);
    }
}

Map<Integer, TitleAndPlace> map = new TreeMap<>();
map.put(1, new TitleAndPlace("T1", "P1"));
map.put(2, new TitleAndPlace("T2", "P2"));

for(Map.Entry<Integer, TitleAndPlace> entry : map.entrySet()){
  System.out.println("ID : " + entry.getKey() + " Title : " + entry.getValue().getTitle() + ", Place: " + entry.getValue().getPlace());
}

【讨论】:

  • 这不是问题所在。在我的问题中,可以将多个值分配给一个 id 或任何值,例如,可以将标题、地点等分配给 ID1
  • @StaOver 我在您的样本数据中看不到任何证据。但不管怎样,看看我更新的答案。
猜你喜欢
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多