2016-06-22 6 views
1

я думал, что я получаю очень хорошо Java 8 потоков, но потом ...Java поток собирают на карту с несколькими ключами

У меня есть Foo интерфейс:

public interface Foo { 
    String getKey(); 
    Stream<Bar> bars(); 
} 

Я знаю, что я могу собрать Stream<Foo> в Map<String, Foo> с помощью ключа каждого:

Map<String, Foo> foosByKey = fooStream.collect(
    Collectors.toMap(Foo::getKey, Function.identity())); 

Но что, если я хочу, чтобы собрать их в Map<Bar, Foo>? Другими словами, для каждого Foo в паре, я хочу поместить это Foo на карту, привязанную к каждому из Bar экземпляров, возвращенных Foo.bars(). С чего начать?

+0

Нет, у вас есть это в обратном порядке. «Карта » будет означать взаимно однозначное сопоставление между экземплярами «Bar» и «Foo». Рассмотрим «Map ' или 'Map ', где у человека может быть несколько кредитных карт, а книга может иметь несколько ISBN. Здесь ничего сложного. –

+0

Я действительно понимаю смысл, но я не хотел зависеть от очков, которые немного вспомогательны. Независимо от того, является ли отображение двунаправленным, зависит от того, является ли график направленным. Java «Карта» является однонаправленной, поэтому вы не можете отобразить обратную сторону - вот почему у Гуавы есть «BiMap», например. Я думаю, вы хотели сказать, что _relationship_ является взаимно однозначным --- в этом случае _relationship_ является много-к-одному ('Bar'-'Foo'). Но опять-таки это все, что связано с точкой - все, что нужно обсудить с пивом. Резюме состоит в том, что каждый 'Foo' может иметь много« баров », и я хочу отобразить' Bar' на 'Foo'. Ура! –

+0

Действительно, мы можем закрыть утверждение о том, что у каждого 'Foo' может быть много« Bar », и что все' Bar' отличаются друг от друга, и, я думаю, [ответ Sotirios] (http://stackoverflow.com/a/37956805/2711488) содержит соответствующее решение. Есть ли что-нибудь, что мешает вам принять его ответ, на что мы должны обратиться? – Holger

ответ

2

Как предложено here, вам нужно извлечь значения Bar из каждого Foo и создать их пары. Когда у вас есть пары, вы можете собрать их в Map. Например,

Map<Bar, Foo> map = fooStream.flatMap(foo -> foo.bars().map(bar -> new SimpleEntry<>(bar, foo))) 
      .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 

Мы используем SimpleEntry здесь, потому что она доступна (Java не имеет более простой Pair типа). Вы могли бы написать свое собственное, чтобы быть более конкретным.

+1

Использование 'SimpleEntry <>' круто --- я не понял, что Java имеет что-то по крайней мере похожее на 'Pair'. В целом, хотя я надеялся на что-то более компактное, но это может быть лучшее, что мы можем получить. Я оставлю его на некоторое время, чтобы узнать, есть ли у нас другие варианты. –

+1

Java 9 добавит возможность использовать 'Map.entry (bar, foo)' для более качественного построения неизменяемых элементов на основе значений. – Holger

 Смежные вопросы

  • Нет связанных вопросов^_^