【问题标题】:Filter a list of Hash map with filter conditions given in another Hash map Java使用另一个 Hashmap Java 中给出的过滤条件过滤 Hashmap 列表
【发布时间】:2020-05-20 22:11:27
【问题描述】:

假设我有一个对象 P 的列表。

Class P {
    int id;
    Map<String,String> value;
}

一个值看起来像

value = {
    "Category" : "Category 1",
    "family" : "Family 1",
    "color" : "Color 1"
}

如上所述,我有 P 的列表。假设列表是 listP。

map1 = {
    "Category" : "Category 1",
    "family" : "Family 1",
    "color" : "Color 1"
}
map2 = {
    "Category" : "Category 2",
    "family" : "Family 2",
    "color" : "Color 1"
}
map3 = {
    "Category" : "Category 1",
    "family" : "Family 1",
    "color" : "Color 2"
}
map4 = {
    "Category" : "Category 2",
    "family" : "Family 1",
    "color" : "Color 1"
}
List<P> listP = [
    P(1, map1),
    P(2, map2),
    P(3, map3),
    P(4, map4),
]

我想根据各种条件进行过滤。条件以地图的形式呈现。

filter = {
   "color" : "Color 1",
   "family" : "Family 1"
}

过滤后,很明显,输出将是

List<P> listP = [
    P(1, map1),
    P(4, map4),
]

ma​​p1ma​​p4 指的是上面 code sn-p 中定义的地图。 长话短说,我想要下面提到的 Python 代码的替代品(不适用于这些类,但想法是一样的。

filterC = {
    "color" : "Color 1",
    "family" : "Family 1"
}

inputL = [
    {
        "Category" : "Category 1",
        "family" : "Family 1",
        "color" : "Color 1"
    },
    {
        "Category" : "Category 1",
        "family" : "Family 1",
        "color" : "Color 2"
    },
    {
        "Category" : "Category 1",
        "family" : "Family 2",
        "color" : "Color 1"
    },
    {
        "Category" : "Category 2",
        "family" : "Family 1",
        "color" : "Color 1"
    },
]

outputL = [inp for inp in inputL if all(inp[k] == v for k,v in filterC.items())]

正如评论中所建议的,我已经为 Product 类的 value 属性添加了我的代码和示例值(上面称为 P)

Map<String, String> filter = new HashMap<String, String>();
        filter.put("Category","7018");
        filter.put("Carbon","0.075");

        List<Product> productList= productRepository.findAll();


        List<Product> prodList = productList.stream()
                .filter(prod -> filter.entrySet().stream().allMatch(e -> prod.getValue().get(e.getKey()) == e.getValue()))
                .collect(Collectors.toList());

样本

{Category=7018, Hydrogen=5, Moisture=0.3, Product Name=New Product, Ferrite (Fn)=, Vanadium=0.025, Phosphorus=0.0175, Hardness=, Carbon=0.075, Molybdenum=0.1, UTS=550, Columbium=, Chromium=0.1, YS=200, Nickel=0.15, Silicon=0.375, Hardness_Scale=HRC, Sulfur=0.0175, Copper=, Elongation=11, Manganese=0.8}

我可以使用普通循环和基本 lambda 来完成任务,但我无法使用过滤器和收集器。任何方向的帮助将不胜感激。我学习了一些教程,但在函数式编程方面我是 Java 新手。提前谢谢。

Edit - 将 P 中的 id 从 String 转换为 int 以避免混淆。与怀疑无关,只是为了清楚

【问题讨论】:

  • 如果您放入实际地图而不是 Json,将对所有人都有帮助。
  • 感谢 WJS 的输入。我已经添加了代码。我的想法是它可能会使任何人感到困惑,所以我避免了它。

标签: java collections functional-programming hashmap java-stream


【解决方案1】:

假设你有如下输入数据

List<Product> products = Arrays.asList(first, second, ..);

你的过滤器映射是

Map<String, String> filters = new HashMap<>();

filters.put("color", "xyz");

然后您可以使用它进行过滤。

List<Product> data = products
  .stream()
  .filter(element -> filter.entrySet()
            .stream()
            .allMatch(criteria -> Objects.equals(criteria.getValue(), 
                            element.getValue().get(criteria.getKey()))))
  .collect(Collectors.toList());

【讨论】:

  • 嘿,@lucid,我附上了我正在尝试的代码。你能指出那里的错误吗?我的代码没有抛出任何错误。它只是过滤空数据。但是,如样本本身所述,至少有一种产品满足过滤条件。而且有很多。
  • @Plasmatiger 问题在于allMatch(e -&gt; prod.getValue().get(e.getKey()) == e.getValue()) 部分,它将匹配参考。你可以用这个Objects.equal(prod.getValue().get(e.getKey()), e.getValue())替换
  • 非常感谢。我觉得很傻。 Java在字符串匹配时的基本错误。感谢您指出正确的方向。拯救了这一天。
  • 乐于助人:)
【解决方案2】:

以下将做你想要实现的目标

List<Product> filteredProducts = products.stream()
            .filter(product -> filter.entrySet()
                    .stream()
                    .allMatch(e -> product.getValue().get(e.getKey()) != null && product.getValue().get(e.getKey()).equals(e.getValue())))
            .collect(Collectors.toList());

基本上遍历列表中的所有元素并过滤过滤器映射中的所有键/值。或者更好的方法是

List<Product> filteredProducts = products.stream()
            .filter(product ->  product.getValue().entrySet().containsAll(filter.entrySet()))
            .collect(Collectors.toList());

过滤器在哪里

Map<String, String> filter = new HashMap<>();
    filter.put("color", "Color 1");
    filter.put("family", "Family 1");

【讨论】:

  • 嘿,@harsh,我附上了我正在尝试的代码。你能指出那里的错误吗?我的代码没有抛出任何错误。它只是过滤空数据。但是,如样本本身所述,至少有一种产品满足过滤条件。还有很多
  • @Plasmatiger 它是==(检查引用等价性)vs equals(检查字符串情况下的内容等价性),但最好使用filter(product -&gt; product.value.entrySet().containsAll(filter.entrySet())),这是一个更清洁的解决方案
  • 是的,@lucid 指出了这一点。感觉很傻。我正在查看谓词中的错误,而它是对象相等。谢谢,评论。拯救了我的一天。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
  • 1970-01-01
  • 2021-06-03
  • 1970-01-01
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
相关资源
最近更新 更多