Java 如果键存在且值不为null,则放入映射,否则抛出异常
我可以用Java8以更好的方式编写它吗?我可以用某种方式将其合并为一个表达式吗?记住,要求是: 如果键存在或值不为null,则放入映射,否则抛出异常 这意味着:Java 如果键存在且值不为null,则放入映射,否则抛出异常,java,java-8,hashmap,Java,Java 8,Hashmap,我可以用Java8以更好的方式编写它吗?我可以用某种方式将其合并为一个表达式吗?记住,要求是: 如果键存在或值不为null,则放入映射,否则抛出异常 这意味着: 如果密钥不存在,则抛出异常 若值为null,则引发异常 放在地图上 您应该首先执行null检查,然后使用该方法并检查返回值,因此只执行一次映射查找 void addToMapIfKeyExists(String k, String v) { if (!map.containsKey(k)) { throw n
- 如果密钥不存在,则抛出异常
- 若值为null,则引发异常
- 放在地图上
void addToMapIfKeyExists(String k, String v) {
if (!map.containsKey(k)) {
throw new NoSuchElementException(k + " does not exist in the map");
}
// else ignore
if (v != null) {
map.put(k, v);
}
}
您可以在一条语句中:
void addToMapIfKeyExists(String k, String v) {
if (v == null)
throw new IllegalArgumentException("Value is null");
if (map.replace(k, v) == null)
throw new NoSuchElementException("Key doesn't exist: " + k);
}
上述规定:
[1] 如果键不在映射中,或者映射为null,则会抛出NoTouchElementException
[2] 否则,如果您试图设置null
,则不会执行任何操作
[3] 否则,将键设置为新值
这显然是您想要的,但这是一个奇怪的需求组合。在最简单的形式中,如下内容可能适合您的需要:
public void overwrite(String k, String v) {
map.compute(k, (key, value) -> {
if (value == null) throw new NoSuchElementException(key + " does not exist in the map");
return v == null ? value : v;
});
}
免责声明:选择此项之前,请明智地做出决定。我将不建议将此作为基于所涉及API的实践
static void addToMapIfKeyExists(String k, String v) {
if (v != null && map.containsKey(k)) { // if key exists and value is not null
map.put(k, v); // Put in the map
} else { // else throw exception
throw new IllegalArgumentException("Else throwing exception.");
}
}
我可以通过以下测试比较这两种方法的行为是否相同:
static void addToMapIfKeyExistsOneLiner(String k, String v) {
map.put(k, Optional.ofNullable(v)
.filter(ignore -> map.containsKey(k))
.orElseThrow(IllegalArgumentException::new));
}
staticmap=newhashmap();
私有静态void comparativeTest(){
放在地图上(“a”,“trying”);
地图。放(“b”,“哭”);
addToMapIfKeyExists(“a”,“works”);
System.out.println(map.get(“a”).equals(“works”);
添加到PIFKEYEXISTSONELINER(“a”,“作品”);
System.out.println(map.get(“a”).equals(“works”);
AddToMapFKeyExists(“b”,null);//null值引发异常
addToMapIfKeyExists(“e”,“新键抛出异常”);
addToMapIfKeyExistsOneLiner(“b”,null);//null值引发异常
addtomapifkeyxistsoneliner(“e”,“新键抛出异常”);
}
@Kayaman,我已经更新并更改了一点问题,有什么想法吗?默认V替换(K键,V值)仅当指定键当前映射到某个值时才替换该项。这不适合你吗?小心替换。检查“returns”中的解释,除了值为null
时的异常处理之外,您已经拥有的已经足够好了,只是需求看起来有点奇怪。这就好像putIfPresent
与正常的put
异常处理一样。你为什么说奇怪?它更原子化。如果地图做出了某些原子保证,则上述内容将是原子的。一个if/else不能被地图原子化,它永远不能知道第二个调用即将到来。这些东西的性能取决于虚拟机、操作系统,尤其是map impl,没有一个答案。对于大多数映射来说,这不会造成任何性能差异。如果更新操作只是在键不在映射中时写入,则更有意义。如果它真的没有覆盖(如果它已经存在的话),那么null处理就很奇怪:如果我想用null覆盖,那么它应该这样做(用null替换该值,或者可能删除该值)。请注意,计算返回“null”意味着:删除。普通的HashMap
不保证原子性,但是单个compute
可能比containsKey
后跟put
更有效,因为它只支持单个哈希查找。您还可以使用if(map.compute(k,(key,value)->v==null?value:v==null)抛出新的NoSuchElementException(key+“在映射中不存在”)代码>;此变量还可用于computeIfPresent
。当键不存在时,此变量将执行put
,并更新现有的映射。除了“Anull
return还可以指示先前将null
与键关联的映射..”@nama关于null
返回值是正确的,但是对该方法的要求将指示不允许null
值,这非常适合map
上的较新方法,类似于replace()
,它将null
值视为不存在的条目。同意将共享实现与null
值处理对齐。但是作为replace
的一个副作用,更新映射超出了addToMapIfKeyExists
的目的。因此,您对这两个问题的回答都是“否”,即问题:“我可以在Java 8中以更好的方式编写它吗?”和“我可以以某种方式将其合并到一个表达式中吗?”,因为此代码基本上与问题代码相同,除了你修复了异常抛出的问题。@Andreas我想也有解决的办法。但主要是滥用了来自JDK的另一个API。所以我不能完全说“不”,谢谢@Naman。您能将您的一行代码与我几个小时前接受的答案进行比较吗?@HarshalParekh我建议您编写一个单元测试,并根据比较这里各种实现的期望进行断言,然后您可以根据您所感觉到的可读性来决定哪个适合您的需要。@Naman,我指的是性能,而不是准确性。很抱歉给你带来了困惑。
static Map<String, String> map = new HashMap<>();
private static void comparativeTest() {
map.put("a", "trying");
map.put("b", "crying");
addToMapIfKeyExists("a", "works");
System.out.println(map.get("a").equals("works"));
addToMapIfKeyExistsOneLiner("a", "works");
System.out.println(map.get("a").equals("works"));
addToMapIfKeyExists("b", null); // null value throw exception
addToMapIfKeyExists("e", "new key throws exception");
addToMapIfKeyExistsOneLiner("b", null); // null value throw exception
addToMapIfKeyExistsOneLiner("e", "new key throws exception");
}