我有一个a类和B类的列表,没有重复的元素。“代码”属性在A类和B类中都是相同的。我想将它们转换为Map
public class A {
private String code;
private boolean status;
field 3...
field 4..
}
public class B {
private String code;
private String location;
field 5...
field 5..
}
public class C {
private String location;
private boolean status;
}
List1 : [A(code=NY, status=false), A(code=NJ, status=true),A(code=TX, status=true), A(code=NM, status=false)]
List2 : [B(code=NY, location=NewYork), B(code=NJ, location=NewJersey),B( code=TX, location=Texas), B(code=NM, location=NewMexico)]
Map = map{NY=C(location=NewYork, status=false), NJ=C(location=NewJersey, status=true), TX=C(location=Texas, status=true),NM=C(location=NewMexico, status=false)}
最终映射的顺序应与列表1中的元素相同
~A
更新:我将代码更新到下面,但它不是编译的。你知道怎么了吗?
package test;
import java.util.*;
import java.util.stream.Collectors;
public class Test {
static void main(String[] args){
new Test().testFunction();
}
void testFunction(){
System.out.println("Hello World");
List<A> listA = Arrays.asList(new A("NY", false), new A("NJ", true), new A("TX", false), new A("AZ", true));
List<B> listB = Arrays.asList(new B("NY", "New York"), new B("NJ", "New Jersey"),
new B("TX", "Texas"), new B("NM", "New Mexico"));
Map<String, B> mapB = listB
.stream()
.collect(Collectors.toMap(B::getCode, b -> b, (b1, b2) -> b1));
Map<String, C> innerJoin = listA
.stream()
.filter(a -> mapB.containsKey(a.getCode())) // make sure a B instance exists with the code
.map(a -> Map.entry(a.getCode(), new C(mapB.get(a.getCode()).getLocation(), a.getStatus())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (c1, c2) -> c1, HashMap::new));
innerJoin.forEach((code, c) -> System.out.println(code + " -> " + c));
}
}
class A {
private String code;
private boolean status;
public A(String code, boolean status) {
this.code = code;
this.status = status;
}
public String getCode() {
return this.code;
}
public boolean getStatus() {
return this.status;
}
}
class B {
private String code;
private String location;
public B(String code, String location) {
this.code = code;
this.location = location;
}
public String getCode() {
return this.code;
}
public String getLocation() {
return this.location;
}
}
class C {
private String location;
private boolean status;
public C(String location, boolean status) {
this.location = location;
this.status = status;
}
public String getLocation() {
return this.location;
}
public boolean getStatus() {
return this.status;
}
}
这个任务似乎是通过一个键属性连接两个对象列表。考虑到需求,它应该像内连接一样借助从listB
创建的临时映射。
Map<String, B> mapB = listB
.stream()
.(Collectors.toMap(B::getCode, b -> b, (b1, b2) -> b1)); // use merge function as a defense measure
Map<String, C> innerJoin = listA
.stream()
.filter(a -> mapB.containsKey(a.getCode())) // make sure a B instance exists with the code
.map(a -> Map.entry(a.getCode(), new C(mapB.get(a.getCode()).getLocation(), a.isStatus())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (c1, c2) -> c1, LinkedHashMap::new));
测试:
List<A> listA = Arrays.asList(new A("NY", false), new A("NJ", true), new A("TX", false), new A("AZ", true));
List<B> listB = Arrays.asList(new B("NY", "New York"), new B("NJ", "New Jersey"), new B("TX", "Texas"), new B("NM", "New Mexico"));
// ...
innerJoin.forEach((code, c) -> System.out.println(code + " -> " + c));
输出:
NY -> C(location=New York, status=false)
NJ -> C(location=New Jersey, status=true)
TX -> C(location=Texas, status=false)
“最简单”的解决方案可能基于这样的假设,即两个列表中的项目由相同的code
字段“排序”,那么不需要临时映射:
Map<String, C> simple = IntStream
.range(0, listA.size())
.mapToObj(i -> Map.entry(listA.get(i).getCode(), new C(listB.get(i).getLocation(), listA.get(i).isStatus())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (c1, c2) -> c1, LinkedHashMap::new));
然而,这样的解决方案太脆弱了。
java prettyprint-override">Map<String, C> map = IntStream.range(0, list1.size())
.mapToObj(i -> new CodeIndex(list1.get(i).code(), i))
.collect(Collectors.toMap(
CodeIndex::code,
ci -> new C(list2.get(ci.index()).location(), list1.get(ci.index()).status()),
(a, b) -> a,
LinkedHashMap::new
));
我们首先获取两个列表的所有有效索引,然后映射到一个(自定义)容器类,其中包含索引和代码。(我称之为CodeIndex
,但您也可以使用Map.Entry
或一些Pair
类。)
最后,我们将其收集到一个LinkedHashMap
(因为它保留了插入顺序),将键映射到简单的CodeIndex::code
,并将值映射到新的C(«location\u from_list2»,«status\u from_list1»)
。
请注意,此代码遍历列表一次。
当然,这是假设:
请注意,我使用了记录样式的getter,即与相应字段名同名的getter。例如,location()
而不是getLocation()
。
你应该使用这样的东西:
Map<String, B> mapList2 = list2.stream().collect(Collectors.toMap(B::getCode,
Function.identity()); // create temporary map
Map<String,B> result = list1.stream().collect(
LinkedHashMap::new,
(map, a) -> map.put(
a.getCode(), // get code from A
new C(
mapList2.get(a.getCode()).getLocation() // get location from B
a.getStatus() // get status from A
),
Map::putAll); // use LinkedHashMap to keep order
我有两份清单: 列表1: Object1(name1, id1) 列表2: Object2(name2, id2) 给定list1的大小与list2相同 我想迭代list2,如果list2的name2不为null,则更新list1的name1。 以下是使用旧java的代码: 用java实现这一点的最佳方法是什么。util。流动
我在迭代一个对象内的列表时遇到了一个问题,该对象内嵌在另一个映射中。我的目标是迭代这个列表并生成一个映射 ,我希望使用streams和lamdas来实现这一点。 我在上面看到了,我需要通过迭代FolderBo中的elementList从elementBo创建一个带有map 的映射。folderBo本身就在Modelbo的地图内。
我有以下课程: 我想使用Java流创建一个
是否可以从迭代器创建一个流,其中对象的序列与通过反复调用迭代器的next()方法生成的序列相同?我所考虑的具体情况涉及到Treeset.desceningIterator()返回的迭代器的使用,但是我可以想象在其他情况下,迭代器是可用的,而不是它所引用的集合。 例如,对于,我们可以编写并按照该集合的排序顺序获取该集合中的对象流,但是如果我们希望它们按照不同的顺序,比如通过使用获得的顺序呢?我想象的
我想知道,如何在Java8中使用流API迭代多级列表 根据Java8,我应该做如下的操作 我想要流利地做这件事(使用内部迭代)。任何解释都会很感激。
我有一个学生名单a和学生名单B。 学生对象包含如下字段:否、年龄、城市、出生日期、工资 我的列表A包含这些对象 我的列表B包含这些对象 我想做的是提取ListA有但listB没有的学生对象,以及ListA和listB有但薪水不同的学生对象(如否、年龄、城市)。我还想写工资差异。 我想在java 8中使用流api。首先,我想将students对象提取到列表中,但我现在可以提取常见的student对象