如何在使用Java的流(Streams)进行比较映射(Maps)时处理空值?

huangapple go评论70阅读模式
英文:

How to handle null while comparing maps using streams - Java?

问题

我有两个数据结构其值如下

    List<Map<String, String>> customerDirectory

```java
[{NAME=ALEX BENSON, PHONE=012-12342, ADDRESS=123 MAIN ST, CITY=QUEENS, STATE=NY},
 {NAME=ZOYE ABEL, PHONE=012-12445, ADDRESS=123 WATERSIDE, CITY=WINDSOR, STATE=CT}]

Map<String, String> customerInfo
{NAME=ALEX BENSON, PHONE=012-12342, ADDRESS=123 MAIN ST}

我正在尝试遍历customerDirectory,以查找customerInfo的值在键"NAME""PHONE""ADDRESS"上是否有完全匹配,以便我可以判断记录是否重复。

所以我想到了:

List<String> compareKeys = Arrays.asList("NAME","PHONE","ADDRESS");

Function<Map<String,String>, String> getVal = mp -> compareKeys.stream().map(mp::get).map(String::trim).collect(Collectors.joining());

BiPredicate<Map<String,String>, Map<String,String>> checkDup = (mp1,mp2) -> getVal.apply(mp1).equals(getVal.apply(mp2));

boolean anyMatch = customerDirectory.stream().anyMatch(customer -> checkDup.test(customerInfo, customer));

但是customerInfo映射的ADDRESS键可以具有值为null,我尝试了:

BiFunction<Map<String, String>, String, String> handleNull = (mp, key) -> mp.get(key) == null ? " " : mp.get(key);

并将其用于:

Function<Map<String,String>, String> getVal = mp -> compareKeys.stream().map(key -> handleNull.apply(mp,key)).map(mp::get).map(String::trim).collect(Collectors.joining());

但我仍然会遇到NullPointerException,这意味着我可能在流程中遗漏了一些内容。是否有更好的方法来处理这里的null值?


<details>
<summary>英文:</summary>

I have 2 data structures with values like:

    List&lt;Map&lt;String,String&gt;&gt; customerDirectory

[{NAME=ALEX BENSON, PHONE=012-12342, ADDRESS=123 MAIN ST, CITY=QUEENS, STATE=NY},
{NAME=ZOYE ABEL, PHONE=012-12445, ADDRESS=123 WATERSIDE, CITY=WINDSOR, STATE=CT}]

and

    Map&lt;String,String&gt; customerInfo

{NAME=ALEX BENSON, PHONE=012-12342, ADDRESS=123 MAIN ST}

I am trying to iterate through the `customerDirectory` to find if `customerInfo` has exact match in values for the keys - `&quot;NAME&quot;,&quot;PHONE&quot;,&quot;ADDRESS&quot;` so that I could find if the record is a duplicate.

So I have come up with:

    List&lt;String&gt; compareKeys = Arrays.asList(&quot;NAME&quot;,&quot;PHONE&quot;,&quot;ADDRESS&quot;);

    Function&lt;Map&lt;String,String&gt;, String&gt; getVal = mp -&gt; compareKeys.stream().map(mp::get).map(String::trim).collect(Collectors.joining());

    BiPredicate&lt;Map&lt;String,String&gt;, Map&lt;String,String&gt;&gt; checkDup = (mp1,mp2) -&gt; getVal.apply(mp1).equals(getVal.apply(mp2));

    boolean anyMatch = customerDirectory.stream().anyMatch(customer-&gt; checkDup.test(customerInfo, customer));

But the `customerInfo` map can have value for `ADDRESS` as `null` for which I have tried:

    BiFunction&lt;Map&lt;String, String&gt;, String, String&gt; handleNull = (mp, key) -&gt; mp.get(key) == null ? &quot; &quot; : mp.get(key);

and I have used it in :

    Function&lt;Map&lt;String,String&gt;, String&gt; getVal = mp -&gt; compareKeys.stream().map(key-&gt;handleNull.apply(mp,key)).map(mp::get).map(String::trim).collect(Collectors.joining());

But I still end up getting `NullPointerException` which means I am missing the exact flow probably.
Is there a better way to handle `null` values here?



</details>


# 答案1
**得分**: 5

如果我正确理解您的问题,那么您只是想找出是否有任何精确匹配,而且您希望将答案保留在 **anyMatch** 中。请尝试使用以下代码进行更新。

```java
Function<Map<String, String>, String> getVal = mp ->
    compareKeys.stream().map(mp::get).filter(Objects::nonNull).map(String::trim)
        .collect(Collectors.joining());
英文:

If i correctly understood your question then you just want to find out is there any exact match or not, and you want to keep your answer in anyMatch. Please try to update your code with below one.

Function&lt;Map&lt;String, String&gt;, String&gt; getVal = mp -&gt; 
    compareKeys.stream().map(mp::get).filter(Objects::nonNull).map(String::trim)
			.collect(Collectors.joining());

答案2

得分: 4

你可以用更好的方式来做,我认为。

boolean anyMatch = customerDirectory.stream()
         .anyMatch(m -> m.entrySet().stream()
           .filter(entry -> compareKeys.contains(entry.getKey()))
           .allMatch(entry -> entry.getValue().equals(customerInfo.get(entry.getKey()))));

甚至更加简洁的写法

boolean anyMatch =
            customerDirectory.stream()
                   .anyMatch(m -> compareKeys.stream()
                            .allMatch(key -> m.get(key).equals(customerInfo.get(key))));
英文:

You can do it in a better way I think.

boolean anyMatch = customerDirectory.stream()
         .anyMatch(m -&gt; m.entrySet().stream()
           .filter(entry -&gt; compareKeys.contains(entry.getKey()))
           .allMatch(entry -&gt; entry.getValue().equals(customerInfo.get(entry.getKey()))));

or even more concise:

 boolean anyMatch =
            customerDirectory.stream()
                   .anyMatch(m -&gt; compareKeys.stream()
                            .allMatch(key -&gt; m.get(key).equals(customerInfo.get(key))));

huangapple
  • 本文由 发表于 2020年5月30日 23:20:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/62104542.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定