鉴于我想过滤键值对象列表。
我的(文档) - 下面示例中的对象看起来像这样
{
"attributeEntityList" : [
{key: 'key1', value: 'somevalue1'},
{key: 'key2', value: 'somevalue2'},
{key: 'key3', value: 'somevalue3'}
]
}
当我传入以下键["key1", "key2", "key3"]
的列表时,我希望我的函数返回整个给定的属性列表。
当我传入以下键["key1", "key2"]
的列表时,我希望我的函数返回一个具有给定键名的属性列表。
当我传入以下键["key1", "key2", "faultyKey"]
的列表时,我希望我的函数返回一个空列表。
我的命令式解决方案看起来像这样,它可以正常工作:
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeEntityList();
final List<AttributeEntity> resultList = new ArrayList<>();
for(String configKey: keys){
boolean keyInAttribute = false;
for(AttributeEntity documentAttribute : documentAttributeList){
if(configKey.equals(documentAttribute.getAttribute_key())){
keyInAttribute = true;
resultList.add(documentAttribute);
break;
}
}
if(!keyInAttribute){
resultList.clear();
break;
}
}
return resultList;
}
对于教育和娱乐(也许更好的扩展),我想知道如何使用新的Java 8 streaming-api将这段代码转换为解决方案。
这就是我想到的,将我的Java8前代码转换为Java8。
在我看来,它看起来更简洁,而且更短。但它没有,我期望它做什么:/
我真的很难实现我的要求的第三个要点。 它总是返回所有(找到的)属性,即使我传入一个不存在的键。
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeList();
return documentAttributeList.stream()
.filter(attribute ->
keys.contains(attribute.getAttribute_key())
).collect(Collectors.toList());
}
我正在考虑实现自己的自定义收集器。 由于我的收集器只应返回List,因为收集的结果至少包含一次给定的键。
关于如何实现这一目标的任何其他想法?
此解决方案通过了我的测试。 但感觉就像我把车推到了马前。
它既不简洁也不简短或优雅。
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeList();
return documentAttributeList.stream()
.filter(attribute ->
keys.contains(attribute.getAttribute_key())
)
.collect(Collectors.collectingAndThen(Collectors.toList(), new Function<List<AttributeEntity>, List<AttributeEntity>>() {
@Override
public List<AttributeEntity> apply(List<AttributeEntity> o) {
System.out.println("in finisher code");
if (keys.stream().allMatch(key -> {
return o.stream().filter(attrbiute -> attrbiute.getAttribute_key().equals(key)).findAny().isPresent();
})) {
return o;
} else {
return new ArrayList<AttributeEntity>();
}
}
}));
}
答案 0 :(得分:3)
首先,我必须说我也是Java 8新功能的新手,因此我对所有内容都不熟悉,并且不习惯函数式编程。我尝试了一种不同的方法,将其全部划分为一些方法。
这是:
public class Main {
private static List<AttributeEntity> documentAttributeList;
static {
documentAttributeList = new ArrayList<>();
documentAttributeList.add(new AttributeEntity("key1", "value1"));
documentAttributeList.add(new AttributeEntity("key2", "value2"));
documentAttributeList.add(new AttributeEntity("key3", "value3"));
}
public static void main(String[] args) {
Main main = new Main();
List<AttributeEntity> attributeEntities = main.getAttributeEntities(Arrays.asList("key1", "key2"));
for (AttributeEntity attributeEntity : attributeEntities) {
System.out.println(attributeEntity.getKey());
}
}
private List<AttributeEntity> getAttributeEntities(List<String> keys) {
if(hasInvalidKey(keys)){
return new ArrayList<>();
} else {
return documentAttributeList.stream().filter(attribute -> keys.contains(attribute.getKey())).collect(toList());
}
}
private boolean hasInvalidKey(List<String> keys) {
List<String> attributeKeys = getAttributeKeys();
return keys.stream().anyMatch(key -> !attributeKeys.contains(key));
}
private List<String> getAttributeKeys() {
return documentAttributeList.stream().map(attribute -> attribute.getKey()).collect(toList());
}
}
答案 1 :(得分:1)
如果一个文档永远不能有多个具有相同名称的属性,我认为你可以这样做(没有编译器方便尝试):
Map<String, AttributeEntity> filteredMap=value.getAttributeEntityList().stream()
.filter(at->keys.contains(at.getKey()))
.collect(toMap(at->at.getKey(), at->at));
return filteredMap.keySet().containsAll(keys)
? new ArrayList<>(filteredMap.values())
: new ArrayList<>();
如果允许每个名称包含多个属性,则必须使用groupingBy而不是toMap。当然,你可以用collectAndThen重写它,但我认为它不太清楚。
答案 2 :(得分:0)
我想出了一些东西。
我不知道它是否是最优雅的解决方案,但至少它是有效的,我可以推理它。
private List<AttributeEntity> getAttributeEntities(List<String> keys, Document value) {
final List<AttributeEntity> documentAttributeList = value.getAttributeList();
boolean allKeysPresentInAnyAttribute = keys.stream()
.allMatch(key ->
documentAttributeList.stream()
.filter(attrbiute ->
attrbiute.getAttribute_key().equals(key)
)
.findAny()
.isPresent()
);
if (allKeysPresentInAnyAttribute) {
return documentAttributeList.stream()
.filter(attribute ->
keys.contains(attribute.getAttribute_key())
)
.collect(Collectors.toList());
}
return new ArrayList<>();
}
任何提示或评论都非常感谢。