我们有
List<persons> persons;
我们需要
Map<age,Map<income,Person>> results
我现在的做法是:
ages.stream().forEach(a -> {
Map<Integer,Person> tmpMap = new HashMap<>();
incomes.stream().forEach(i -> {
Person p = persons.stream().filter(
u -> u.getAge() == a.getAge() &&
u.getIncome() == i.getIncome())
.findAny().orElse(null);
tmpMap.put(i.getIncome(), p);
});
returns.put(a.getAge(),tmpMap);
});
似乎应该有更好的方法来做到这一点。
答案 0 :(得分:3)
这应该可以解决问题
List<person> persons = Arrays.asList(
new person(22, 1000),
new person(25, 1500),
new person(22, 2500),
new person(32, 5000)
);
Map<Integer, Map<Integer, List<person>>> map = persons.stream().collect(
groupingBy(person::getAge, groupingBy(person::getIncome))
);
System.out.println(map);
<强>输出:强>
{32={5000=[person{age=32, income=5000}]}, 22={2500=[person{age=22, income=2500}], 1000=[person{age=22, income=1000}]}, 25={1500=[person{age=25, income=1500}]}}
NB:结果并不完全符合您的预期,因为您会获得Map<Integer, Map<Integer, List<person>>>
而不是Map<Integer, Map<Integer, person>>
,但我认为您的初始问题不正确,因为如果您有两个年龄和收入相同的人,你的地图中只有一个人而不是两个人
答案 1 :(得分:3)
这看起来很有效。
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()
))));
我使用Map<Age,List<Person>>
将您的列表滚动到groupingBy
,然后流式传输它的entrySet并将其收集到最终表单中。
如果两个年龄相同的人有相同的收入,这将失败,因为这会违反内部地图。如果您对生成Map<Integer, Map<Integer, List<Person>>>
的自然增强感到满意,请使用Alexander's suggestion。
<强>加强>
Map<Integer, Map<Integer, Person>> map2 = people.stream()
.collect(
Collectors.groupingBy(
Person::getAge,
Collectors.toMap(Person::getIncome, Function.identity())));
仅供参考 - 这是我使用的Person类。请注意equals
和hashcode
已实施。
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;
}
}
答案 2 :(得分:2)
你应该看一下 Collectors.groupingBy():
List<Person> persons = new ArrayList<>();
Map<Integer, Map<Integer, List<Person>>> map = persons.stream().collect(Collectors.groupingBy(person -> person.getAge(),Collectors.groupingBy(person -> person.getIncome())));
这应该做你的事。
答案 3 :(得分:1)
为什么不(我认为你的类型是人,而不是人,你同时使用)
for (person p : persons)
{
if (!results.containsKey(p.getAge())
results.put(p.getAge(), new HashMap<income,persons>());
results.get(p.getAge()).put(p.getIncome(), p);
}
答案 4 :(得分:0)
我是第二个YaRiK; Guava Table<Integer, Integer, Set<Person>>
在这里可以很好地运作。您应该使用Set<Person>
来避免冲突,例如user902383建议。流API并不总是正确的工具,这在我看来就像传统的迭代循环much easier to read。
试试这个:
Table<Integer, Integer, Set<Person>> table = HashBasedTable.create();
for (Person p : persons) {
Set<Person> s = table.get(p.getAge(), p.getIncome());
if (s == null) {
s = new HashSet<>();
table.put(p.getAge(), p.getIncome(), s);
}
s.add(p);
}
答案 5 :(得分:0)
您还可以实现自己的收集器来实现此目的。在番石榴的帮助下,您可以在一行中完成:
Map<Integer, Map<Integer, Person>> result = persons.stream().collect(HashMap::new, (store, person) -> store.put(person.getAge(), ImmutableMap.of(person.getIncome(), person)), HashMap::putAll);