【问题标题】:How to filter a hashmap with specific conditions如何过滤具有特定条件的哈希图
【发布时间】:2021-12-28 18:14:55
【问题描述】:

我有以下初始哈希图:

LatS=[59, 48, 59, 12, 48]

LatD=[41, 42, 46, 42]

EW=[W, W, W, W]

NS=[N, N, N, N]

LonM=[39, 23, 30, 48]

州=[OH、SD、WA、MA]

LatM=[5, 52, 35, 16]

City=[扬斯敦、扬克顿、亚基马、伍斯特]

LonS=[0, 23, 36, 0]

LonD=[80, 97, 120, 71]

我想使用具有以下调用的方法查询来过滤 Hashmap:

HashMap<Object, List<Object>> result = df.query( map -> "Youngstown".equals(df.getFrameInfo().get("City").get(0)))

函数的定义是:

`public HashMap<Object, List<Object>> query(Predicate<Object> cond){

    HashMap<Object, List<Object>> ref = new HashMap<>(frameInfo);

        Map<Object, List<Object>> result = ref.entrySet()
                .stream()
                .filter(cond)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        System.out.println("Result: " + result);`

但最困难的部分是通过特定的方式获取hashmap结果。我只想将城市的列作为参数传递。

例如:如果我使用这个参数:

HashMap&lt;Object, List&lt;Object&gt;&gt; result = df.query( map -&gt; "Youngstown".equals(df.getFrameInfo().get("City").get(0)))

输出应该是:

LatS=[59]
LatD=[41]
EW=[W]
NS=[N]
LonM=[N]
State=[OH]
LatM=[5]
City=[Youngstown]
LonS=[0]
Lond=[80]

非常感谢您!

【问题讨论】:

  • 似乎必须为给定的城市名称定义城市索引,然后为该索引返回过滤后的地图。
  • 如果我用另一种方法得到相同的结果可以吗?
  • 我对此有一个答案,但与其他回答者一样,我不明白您选择的功能。你能进一步解释一下吗?另外,什么是 df 和 getFrameInfo() 方法?需要更多信息。

标签: java filter stream hashmap


【解决方案1】:

问题

首先,调用:

df.query(map -> "Youngstown".equals(df.getFrameInfo().get("City").get(0)))

真的没有意义,就像在您的特定情况下一样,前提是谓词始终评估为true - 然后您将其传递给filter()。 请注意,您根本没有使用谓词的 map 变量。

可能的解决方案

我建议在query 方法中添加额外的参数,表示我们正在查询哪个“键”(假设我们希望始终查询单个键)。

然后,为值传递谓词,它将在列表中为特定“键”找到值。

我们将获取找到值的索引,然后通过提取该索引上所有键的值来构造最终的Map

public Map<Object, List<Object>> query(String keySelector, Predicate<Object> valuePredicate) {
    final List<Object> row = frameInfo.get(keySelector);
    final List<Integer> indices = getColumnIndex(row, valuePredicate);

    return getColumnMap(indices);
}

private List<Integer> getColumnIndex(List<Object> row, Predicate<Object> valuePredicate) {
    return IntStream.range(0, row.size()).filter(columnIndex -> valuePredicate.test(row.get(columnIndex))).boxed().collect(Collectors.toList());
}

private Map<Object, List<Object>> getColumnMap(List<Integer> columnIndices) {
    final Map<Object, List<Object>> result = new HashMap<>();
    for (Map.Entry<Object, List<Object>> entry : frameInfo.entrySet()) {
        for (int columnIndex : columnIndices) {
            result.putIfAbsent(entry.getKey(), new ArrayList<>());
            result.get(entry.getKey()).add(entry.getValue().get(columnIndex));
        }
    }
    return result;
}

// Example call
final Map<Object, List<Object>> result = df.query("City", "Youngstown"::equals);
System.out.println(result);

【讨论】:

  • 难以置信的答案 hradecek!但是,如果你想放置一个整数谓词,你会怎么做?因为当我输入: df.query("LatS", entry -> entry instanceof Integer && ((Integer)entry) > 58) 它什么也没找到。我的意思是......它出错了,我应该能够引入我想要的任何谓词。
  • 我已经更新了答案,所以可以返回多个值...我已经根据问题中提供的数据测试了您的查询(复制和粘贴),返回的结果是:{LatS=[59, 59], LatD=[41, 46], EW=[W, W], NS=[N, N], LonM=[39, 30], State=[OH, WA], LatM=[5, 35], City=[Youngstown, Yakima], LonS=[0, 36], LonD=[80, 120]}
  • 是的,我也测试过!很好的答案,更完整。
  • 很高兴它正在工作。如果没问题,请点赞并将我的回答标记为已接受。
  • hradecek 最后一件事。如果你想放置一个整数谓词,你会怎么做?我试过这样做: df.query("LatS", entry -> entry instanceof Integer && ((Integer)entry) > 58) 但它没有通过过滤器并给我一个空地图
猜你喜欢
  • 2015-09-11
  • 1970-01-01
  • 2019-04-18
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
  • 2020-08-23
  • 2013-03-05
相关资源
最近更新 更多