2015-06-25 3 views
4

Что у меня есть:трансформирующий Map <Key, Список <Value>> к карте <Key, Value>

SortedSet<Person> ss = new TreeSet<>(); 

    ss.add(new Person("John", "Doe", 20)); 
    ss.add(new Person("Max", "Power", 26)); 
    ss.add(new Person("Bort", "Bort", 30)); 
    ss.add(new Person("Scorpio", "McGreat", 56)); 

    Map<Integer, List<Person>> list = ss.stream().collect(Collectors.groupingBy(p -> p.name.length())); 

Мне нужно преобразовать карту в Map<Integer, Person> я знаю, что нужно использовать flatMap для этой цели, но я не секрет производства.

Что я пробовал: Получить значение и установить его.

Map <Integer, Person> list2 = list.values() 
            .stream() 
            .flatMap(f -> f.stream()) 
            .collect(Collectors.groupingBy(f -> f.name.length()); //doesn't work 

Вопрос: Насколько я понимаю, Java возвращает значения в виде списков, при создании карты через потоки, как я могу flatMap эти списки?

Дополнительная информация: Реализация CompareTo

@Override 
public int compareTo(Person o) { 

    int cmp = this.surname.compareTo(o.surname); 
    if(cmp == 0){ 
     cmp = this.name.compareTo(o.name); 
    } 

    return cmp; 
} 

ОТКАЗ:

Я знаю, что вариант использования немного странно, так как я сортирую по длине, а также использовать СотрагеТо путем сравнения длина имени. ИМХО это не имеет значения для этого вопроса, так как я всегда получаю Map<Key, List<Value>>. Вопрос IS: Как я могу получить Map<Key,Value>

+1

Что делать, если у вас есть два названия с той же длины? –

+0

На самом деле ваше требование не имеет смысла. Вы хотите группировать по свойству, что означает, что это не обязательно биективная функция. Таким образом, тип значений результирующей карты по умолчанию является списком. Если вы знаете, что функция, которую вы применяете, является биективной, вы можете предоставить другой коллектор нисходящего потока/или использовать сборщик 'toMap', имеющий металическое слияние в качестве параметра (лучший вариант IMO). –

+0

Если два имени в точности равны (согласно compareTo), то Person не будет добавлен в список, так как это Set, но imho это не имеет решающего значения для вопроса о том, как flatMap список. – SklogW

ответ

3

На самом деле ваше требование не имеет смысла. Вы хотите группировать по свойству, что означает, что это не обязательно биективная функция. Таким образом, тип значений результирующей карты по умолчанию является списком. Если вы знаете, что функция, которую вы применяете, является биективной, вы можете поставить другой нисходящий коллектор/или использовать коллекционер toMap, имеющий металическое слияние в качестве параметра (лучший вариант IMO).

Так, например:

Map<Integer, Person> list = 
    ss.stream() 
     .collect(Collectors.toMap(p -> p.surname.length(), 
           p -> p, 
           (p1, p2) -> {throw new IllegalStateException("Duplicate key with length " + p1.surname.length());})); 

выходы в вашем случае:

{3=(John, Doe, 20), 4=(Bort, Bort, 30), 5=(Max, Power, 26), 7=(Scorpio, McGreat, 56)} 
+0

Спасибо! Я попробую это. Если прецедент слишком запутан, я изменю его. Именно то, что мне нужно. Благодарю вас, сэр. – SklogW

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