当前位置: 首页 > 知识库问答 >
问题:

如何使用Lambda表达式对KeyValue对象执行按键过滤?

戚侯林
2023-03-14

考虑到我想过滤键值对象列表。

我的(文档)-对象从下面的例子看起来像这样

{
    "attributeEntityList" : [
        {key: 'key1', value: 'somevalue1'},
        {key: 'key2', value: 'somevalue2'},
        {key: 'key3', value: 'somevalue3'}
    ]
}

>

当我传入以下键的列表时,[“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;
}

为了教育和乐趣(也许还有更好的扩展),我想知道如何使用新的Java8流媒体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());
}

我正在考虑实现自己的定制收集器。因为我的收集器应该只返回列表,当收集的结果至少包含每个给定键一次时。

关于如何实现这一点,还有其他想法吗?

这个解决方案通过了我的测试。但感觉就像是本末倒置。

它不再简洁、简短或优雅。

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>();
                    }
                }
            }));
}

共有3个答案

经俊茂
2023-03-14

我想出了一个办法。

我不知道这是否是最优雅的解决方案,但至少它是有效的,我可以对此进行推理。

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<>();
}

任何提示或意见非常感谢。

文增
2023-03-14

如果一个文档永远不能有多个同名属性,我想你可以这样做(手头没有编译器可以尝试):

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。当然,你可以用CollectingAnd重写这个,但我认为它不那么清晰。

刘畅
2023-03-14

首先,我必须说,我对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());
    }

}
 类似资料:
  • 如何在lambda表达式中将对象设置为另一个?我犯了错误

  • 我试着取一个数字列表,过滤掉偶数,然后平方这些偶数,这样原始列表中的偶数就平方了。这是我的代码: 我尝试了一些其他的方法,但这是我目前所处的位置

  • 这个问题有一个关于如何使用多行lambda表达式对List进行排序的答案: 不幸的是,这似乎不适用于原始数组: 如何在Arrays.sort()中使用多行lambda表达式对原始数组进行排序? 我对任何其他方法(不必使用)都很好,只要它使用lambda表达式(没有比较器)。

  • 你好我想对新创建的LinkedList进行升序排序,列表中的所有元素都是随机装箱的。我的任务是用比较器对它们进行排序,但我不允许编写实现比较器的类,而是应该用lambda表达式对其进行排序。这是我目前的代码: 到目前为止,我尝试使用集合和列表中的排序方法,但无法进一步帮助我。非常感谢您提前帮助我。

  • 我试图用Lamdas简化我的对象创建。 如下所示:

  • 有人知道一种方法(如果可能的话也可以使用lodash)通过对象键对对象数组进行分组,然后根据分组创建新的对象数组吗?例如,我有一个汽车对象数组: 我想制作一个由分组的新汽车对象数组: