Multimap значения гуавы

У меня есть этот сценарий:

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) для хранения идентификатора и заголовка с несколькими значениями:

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?

1 ответ

Решение

Я не думаю, что вы правильно понимаете, что такое Multimap. Multimap отображает один или несколько ключей на несколько значений, это отношение n-to-m. Кажется, у вас есть отношение от идентификатора к заголовку, то есть отношение n-к-1. Правильная структура данных для этого - Карта, а не Мультикарта.

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());
}

Это должно дать желаемый результат.

Примечание: если вы, вероятно, будете искать заголовки по идентификатору на карте, то вы, вероятно, захотите переключиться с 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 Сортирует карту по ключу, 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());
}

Но это не идеальный матч. Если вы хотите отобразить идентификатор на заголовок и место, то, возможно, вы захотите иметь пользовательский объект, инкапсулирующий заголовок и место, и использовать его в качестве значения в простой старой карте от целого числа до пользовательского типа.

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());
}
Другие вопросы по тегам