【发布时间】:2019-01-26 14:53:20
【问题描述】:
我有两个相同类型“MyInfoObject”的列表(比如 A 和 B):
public class MyInfoObject {
private Long id;
private String signature;
public MyInfoObject(Long id, String signature) {
super();
this.id = id;
this.signature = signature;
}
}
我想创建这两个列表的映射,以便列表 A 的所有 id 和具有相同签名的列表 B 的所有 id 创建一个类型为“BucketOfAandB”的存储桶:
public class BucketOfAandB {
private List<Long> aIds ;
private List<Long> bIds ;
public BucketOfAandB(List<Long> aIds, List<Long> bIds) {
super();
this.aIds = aIds;
this.bIds = bIds;
}
}
所以,我的输出将是Map<String, BucketOfAandB>,其中密钥是签名
例如我的输入是:
List<MyInfoObject> aList = new ArrayList<>();
aList.add(new MyInfoObject(1l, "a"));
aList.add(new MyInfoObject(2l, "d"));
aList.add(new MyInfoObject(3l, "b"));
aList.add(new MyInfoObject(4l, "a"));
aList.add(new MyInfoObject(5l, "a"));
aList.add(new MyInfoObject(6l, "c"));
aList.add(new MyInfoObject(7l, "a"));
aList.add(new MyInfoObject(8l, "c"));
aList.add(new MyInfoObject(9l, "b"));
aList.add(new MyInfoObject(10l, "d"));
List<MyInfoObject> bList = new ArrayList<>();
bList.add(new MyInfoObject(11l, "a"));
bList.add(new MyInfoObject(21l, "e"));
bList.add(new MyInfoObject(31l, "b"));
bList.add(new MyInfoObject(41l, "a"));
bList.add(new MyInfoObject(51l, "a"));
bList.add(new MyInfoObject(61l, "c"));
bList.add(new MyInfoObject(71l, "a"));
bList.add(new MyInfoObject(81l, "c"));
bList.add(new MyInfoObject(91l, "b"));
bList.add(new MyInfoObject(101l, "e"));
在这种情况下我的输出将是:
{
a= BucketOfAandB[aIds=[1, 4, 5, 7], bIds=[11, 41, 51, 71]],
b= BucketOfAandB[aIds=[3, 9], bIds=[31, 91]],
c= BucketOfAandB[aIds=[6, 8], bIds=[61, 81]],
d= BucketOfAandB[aIds=[2, 10], bIds=null],
e= BucketOfAandB[aIds=null, bIds=[21, 101]],
}
我想使用 java 8 的 Streams 来实现。
我想到的一种方法是:
- 从
aList创建Map<String, List<Long>>,比如aBuckets - 迭代 bList 并通过以下方式创建
resultantMap<String, BucketOfAandB>- 2a。将具有相同签名的 aBucket 中的列表设置为结果,将其从
aBuckets中删除 - 2b。将
bList的元素添加到所需的签名桶中
- 2a。将具有相同签名的 aBucket 中的列表设置为结果,将其从
- 迭代
aBuckets的所有剩余元素并将它们添加到resultant
我想知道使用 Java 8 的 Streams 实现此功能的更好方法。
提前致谢!
编辑: 我尝试使用流,但对实现不太满意。以下是我的逻辑:
Map<String, BucketOfAandB> resultmap = new HashMap<>();
// get ids from aList grouped by signature
Map<String, List<Long>> aBuckets = aList.stream().collect(Collectors.groupingBy(MyInfoObject::getSignature,
Collectors.mapping(MyInfoObject::getId, Collectors.toList())));
// iterate bList and add it to bucket of its signature
bList.forEach(reviewInfo -> {
BucketOfAandB bucket = resultmap.get(reviewInfo.getSignature());
if(null == bucket) {
bucket = new BucketOfAandB();
resultmap.put(reviewInfo.getSignature(), bucket);
List<Long> sourceReviewBucket = aBuckets.remove(reviewInfo.getSignature());
if(null !=sourceReviewBucket) {
bucket.setaIds(sourceReviewBucket);
}
}
bucket.addToB(reviewInfo.getId());
});
Map<String, BucketOfAandB> result = aBuckets.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> new BucketOfAandB(e.getValue(), null)));
resultmap.putAll(result);
【问题讨论】:
-
如果您添加算法的实现,可能会更容易将其转换为流和 lambda n 的东西。
-
将数据分成 a,b,c,d,e 背后的逻辑是什么?如果您告诉我们这可能会有所帮助。
-
@JackFlamp 我在上面的编辑中添加了我的实现。希望有帮助
标签: java lambda collections java-8 java-stream