[英]Create a map from two different lists based on common conditions using Java 8 Streams
I have two list instances like this: 我有两个这样的列表实例:
List<NameAndAge> nameAndAgeList = new ArrayList<>();
nameAndAgeList.add(new NameAndAge("John", "28"));
nameAndAgeList.add(new NameAndAge("Paul", "30"));
nameAndAgeList.add(new NameAndAge("Adam", "31"));
List<NameAndSalary> nameAndSalaryList = new ArrayList<>();
nameAndSalaryList.add(new NameAndSalary("John", 1000));
nameAndSalaryList.add(new NameAndSalary("Paul", 1100));
nameAndSalaryList.add(new NameAndSalary("Adam", 1200));
where NameAndAge
is NameAndAge
位置
class NameAndAge {
public String name;
public String age;
public NameAndAge(String name, String age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + ": " + age;
}
}
and NameAndSalary
is 和
NameAndSalary
是
private class NameAndSalary {
private String name;
private double salary;
public NameAndSalary(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public String toString() {
return name + ": " + salary;
}
}
Now, I want to create a map with key as NameAndAge
object from the first list and value as NameAndSalary
from the second list where the name is equal in both the objects. 现在,我想从第一个列表中创建一个带有键作为
NameAndAge
对象的映射,并从第二个列表中创建名称为NameAndSalary
值,其中两个对象中的名称相等。
So, when I print the map, it should look like this: 所以,当我打印地图时,它应该如下所示:
{John: 28=John: 1000.0}
{Paul: 30=Paul: 1100.0}
{Adam: 31=Adam: 1200.0}
I have tried doing this, but the end return type is 'void' so I'm stuck clueless as I am new to Streams. 我已经尝试过这样做了,但是结束返回类型是'无效'所以我无所畏惧,因为我是Streams的新手。
nameAndAgeList
.forEach(n ->
nameAndSalaryList
.stream()
.filter(ns -> ns.name.equals(n.name))
.collect(Collectors.toList()));
Can someone please advise how can this be achieved with Java Streams API? 有人可以建议如何使用Java Streams API实现这一目标吗?
First of all, assuming you are going to create a HashMap
, your key class ( NameAndAge
) must override equals
and hashCode()
. 首先,假设您要创建
HashMap
,您的密钥类( NameAndAge
)必须覆盖equals
和hashCode()
。
Second of all, in order to be efficient, I suggest you first create a Map<String,NameAndSalary>
from the second List
: 其次,为了提高效率,我建议你先从第二个
List
创建一个Map<String,NameAndSalary>
:
Map<String,NameAndSalary> helper =
nameAndSalaryList.stream()
.collect(Collectors.toMap(NameAndSalary::getName,
Function.identity()));
Finally, you can create the Map
you want: 最后,您可以创建所需的
Map
:
Map<NameAndAge,NameAndSalary> output =
nameAndAgeList.stream()
.collect(Collectors.toMap(Function.identity(),
naa->helper.get(naa.getName())));
This should do the trick, too: 这也应该可以解决问题:
Map<NameAndAge, NameAndSalary> map = new HashMap<>();
nameAndAgeList.forEach(age -> {
NameAndSalary salary = nameAndSalaryList.stream().filter(
s -> age.getName().equals(s.getName())).
findFirst().
orElseThrow(IllegalStateException::new);
map.put(age, salary);
});
Mind that it would throw an IllegalStateException
if a matching name can't be found. 请注意,如果找不到匹配的名称,它将抛出
IllegalStateException
。
This should work too 这应该也有效
List<String> commonNames = nameAndAgeList
.stream()
.filter(na ->
nameAndSalaryList.anyMatch((ns) -> ns.getName().equals(na.getName()))
.collect(Collectors.toList());
Map<NameAndAge, NameAndSalary> map =
commonNames.stream().collect(Collectors.toMap(name ->
nameAndAgeList.get(name), name -> nameAndSalaryList.get(name)));
Without creating any intermediate object, without using a forEach
, one liner: 没有创建任何中间对象,不使用
forEach
,一个衬垫:
Map<NameAndAge, NameAndSalary> resultMap1 = nameAndAgeList.stream()
.map(nameAndAge -> nameAndSalaryList.stream()
.filter(nameAndSalary -> nameAndAge.getName().equals(nameAndSalary.getName()))
.map(nameAndSalary -> new SimpleEntry<>(nameAndAge, nameAndSalary))
.collect(Collectors.toList()).get(0))
.collect(Collectors.toMap(simpleEntry -> simpleEntry.getKey(), simpleEntry -> simpleEntry.getValue()));
You will have to add the getter
functions to the domain classes though. 您必须将
getter
函数添加到域类中。 Accessing the properties directly might not be a good idea. 直接访问属性可能不是一个好主意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.