检查映射是否仅包含一组键的非空值

问题描述 投票:0回答:5

我有一张地图如下

Map<String, String> myMap = new HashMap<>();
myMap.put("a", "Something");
myMap.put("b", null);
myMap.put("c", "more");

还有一个清单,

List<String> myList = Arrays.asList("a","b");

我想检查 myMap 中带有 myList 中键的所有值是否都为 null

我创建了一个方法,如下所示,效果很好。我想检查我们是否可以使用流在一行代码中实现相同的目标

myMap.values().removeIf(Objects::isNull);

Map<String, String> resultMap = myList.stream().filter(myMap::containsKey).collect(Collectors.toMap(Function.identity(), myMap::get));
if(!resultMap.isEmpty()){
// Atleast one not null value is present in myMap with key in myList
}
java java-8 hashmap java-stream
5个回答
4
投票

当然,只需检查列表中的所有元素是否与映射中的非空值匹配即可:

myList.stream().allMatch(x -> myMap.containsKey(x) && myMap.get(x) == null);
// or (more overhead, but you might prefer its expressivness):
myList.stream()
    .filter(myMap::containsKey)
    .map(myMap::get)
    .allMatch(Objects::isNull);

或者,如果您认为“缺少键”相当于“具有 null”:

myList.stream().map(myMap::get).allMatch(Objects:isNull);

1
投票

Map.get
指定不存在的键返回 null。因此,您只需进行一次空检查即可过滤掉映射到空或根本未映射的键。

Map<String, String> resultMap = myList.stream()
    .filter(key -> myMap.get(key) != null)
    .collect(Collectors.toMap(Function.identity(), myMap::get));

如果您不需要

resultMap
,则使用
anyMatch

会更短
myList.stream().allMatch(key -> myMap.get(key) != null)

myMap.values().removeIf(Objects::isNull)
不同,这不会修改原始地图。


1
投票

因此,您已经使用此行删除了具有

null
values 的条目:

myMap.values().removeIf(Objects::isNull);

很好,因为在集合中保留空引用是一种反模式,因为这些元素无法提供任何有用的信息。因此,我认为您的意图与检查

myList
中的所有字符串是否与
null
相关(或不存在)无关。

现在要检查

myMap
是否包含
myList
中的任何元素(这将自动暗示映射到此类元素的 valuenon-null),您可以在
myList
的内容上创建一个流并根据 myMap
key-set
检查每个元素:

boolean hasNonNullValue = myList.stream().anyMatch(myMap.keySet()::contains);

我怀疑您可能会使用此类(如果有)执行某些操作。如果是这样,那么生成这些 keys 的列表是有意义的,而不是执行上面提供的检查:

List<String> keysToExamine = myList.stream()
    .filter(myMap.keySet()::contains)
    .toList(); // for JDK versions earlier then 16 use .collect(Collectors.toList()) instead of toList()

注意:根据key-set检查list的元素,相反,否则可能会导致性能下降。


1
投票

Stream#findAny
Optional#ifPresent

如果

myMap
中至少存在一个非空值且
myList
中存在相应的键,那么您似乎想要执行某些操作。如果是的话,这个组合就完美满足你的要求了。

myMap.keySet()
    .stream()
    .filter(k -> myMap.get(k) != null && myList.contains(k))
    .findAny()
    .ifPresent(
        // Atleast one not null value is present in myMap with key in myList
        System.out::println // A sample action
    );

演示


0
投票
import javax.xml.bind.*;
import java.io.StringReader;
import java.util.List;

@XmlRootElement(name = "audit-record")
public class AuditRecord {
    private List<AuditEntry> auditEntries;

    @XmlElement(name = "audit-entry")
    public List<AuditEntry> getAuditEntries() {
        return auditEntries;
    }

    public void setAuditEntries(List<AuditEntry> auditEntries) {
        this.auditEntries = auditEntries;
    }
}

class AuditEntry {
    private String name;
    private String value;

    @XmlElement
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlElement
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}



ublic class XMLParserUsingJAXB {
    public static void main(String[] args) {
        String xmlString = "<audit-record>\n" +
                "    <audit-entry>\n" +
                "        <name>descrption</name>\n" +
                "        <value>some value which contains strange characters</value>\n" +
                "    </audit-entry>\n" +
                "    <audit-entry>\n" +
                "        <name>resister number</name>\n" +
                "        <value>123456</value>\n" +
                "    </audit-entry>\n" +
                "</audit-record>";

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(AuditRecord.class);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            AuditRecord auditRecord = (AuditRecord) unmarshaller.unmarshal(new StringReader(xmlString));

            List<AuditEntry> auditEntries = auditRecord.getAuditEntries();
            for (AuditEntry entry : auditEntries) {
                if ("descrption".equals(entry.getName())) {
                    System.out.println("Value under description: " + entry.getValue());
                    break; // Assuming you only need the value once
                }
            }
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.