![](/img/trans.png)
[英]Intercepting calls to Java 8 lambda-expressions using Byte Buddy
[英]How to perform filtering by Key on KeyValue objects using Lambda-Expressions?
鑒於我想過濾鍵值對象列表。
我的(文檔) - 下面的示例中的對象看起來像這樣
{
"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>();
}
}
}));
}
首先,我必須說我也是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());
}
}
如果一個文檔永遠不會有多個具有相同名稱的屬性,我認為你可以這樣做(沒有編譯器方便嘗試):
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重寫它,但我認為它不太清楚。
我想出了一些東西。
我不知道它是否是最優雅的解決方案,但至少它是有效的,我可以推理它。
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<>();
}
任何提示或評論都非常感謝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.