Das sieht aus wie es funktioniert.
List<Person> people = Arrays.asList(
new Person("One", 21, 100),
new Person("Two", 21, 75),
new Person("Three", 42, 100),
new Person("Four", 42, 120),
new Person("Five", 9, 100)
);
Map<Integer, Map<Integer, Person>> map = people.stream()
// Gather all ages into a Map<Age,List<Person>>
.collect(Collectors.groupingBy(Person::getAge))
// Walk that transient Map.
.entrySet().stream()
.collect(Collectors.toMap(
// Key is the age.
Map.Entry::getKey,
// Value is a Map<income,person>
e -> e.getValue()
// Roll each of the same age into a Map<Income,Person>
.stream().collect(
Collectors.toMap(
// Key is income.
Person::getIncome,
// Value is the Person.
Function.identity()
))));
ich rolle Ihre Liste in eine Map<Age,List<Person>>
ein groupingBy
und anschließend streamen es entrySet ist und sammeln, die in die endgültige Form.
Dies wird fehlschlagen, wenn zwei Personen im gleichen Alter das gleiche Einkommen haben, weil das die innere Karte verletzen wird. Verwenden Sie Alexander's suggestion, wenn Sie mit der natürlichen Verbesserung der Generierung eines Map<Integer, Map<Integer, List<Person>>>
zufrieden sind.
Added
@Holger hat in einem Kommentar darauf hingewiesen, dass dies in eine viel einfacher und eleganter Weise erfolgen. Bitte verwenden Sie dieses Formular stattdessen/
Map<Integer, Map<Integer, Person>> map2 = people.stream()
.collect(
Collectors.groupingBy(
Person::getAge,
Collectors.toMap(Person::getIncome, Function.identity())));
FYI - Hier ist die Personenklasse, die ich verwendet habe.Beachten Sie, dass die equals
und hashcode
implementiert sind.
class Person {
private final String name;
private final int age;
private final int income;
public Person(String name, int age, int income) {
this.name = name;
this.age = age;
this.income = income;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getIncome() {
return income;
}
@Override
public String toString() {
return "Person{" + "name=" + name + ", age=" + age + ", income=" + income + '}';
}
@Override
public int hashCode() {
int hash = 7;
hash = 59 * hash + Objects.hashCode(this.name);
hash = 59 * hash + this.age;
hash = 59 * hash + this.income;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if (this.age != other.age) {
return false;
}
if (this.income != other.income) {
return false;
}
if (!Objects.equals(this.name, other.name)) {
return false;
}
return true;
}
}
Haben Sie Guava Bibliothek in Betracht gezogen? Ich glaube, es hat die Umsetzung für das, was Sie brauchen. – YaRiK
Nicht sicher, wie Ihre Karte und Klassen aussehen, aber wissen Sie, dass Sie möglicherweise ein Problem haben, wenn paar Personen Alter oder Einkommen teilen – user902383
Seitliche Anmerkung: Java Klassennamen beginnen mit Großbuchstaben per Konvention. Das Ignorieren dieser Konvention erschwert es anderen Java-Programmierern, Ihren Code zu lesen. also überlege, das zu beheben. – GhostCat