2011-11-28 143 views
3

在Python,我可以做到以下几点:的Java:HashMap的:得到:指定默认值

d = { 'a': True, 'b': False } 
print d.get('x', True) 

它将打印

True 

在Java中,HashMap.get方法不具有的第二个参数指定一个默认值。什么是实现这一目标的正确,简洁和可读的方式?下面的表达式显得过于冗余的对我说:

map.containsKey("x") ? map.get("x") : true 
+1

我认为你发布它的方式(编辑之后)几乎是用纯Java编写它的最短途径 – soulcheck

回答

0

两者都是错误的,因为他们会做2次查找。 通常你会想做的事:

Boolean ret = map.get("x"); 
if (ret == null) { 
    return true 
} 
return ret; 

你可以在一个函数包装这个

public static <K,V> V mapGet(Map<K, V> map, K key, V defaultValue) { 
    V ret = map.get(key); 
    if (ret == null) { 
     return defaultValue; 
    } 
    return ret; 
} 

你可以,如果你想成为非静态的。如果你是实例化地图对象的人(你不能从外部代码获得它),你可以继承hashmap。如果一个API返回地图实例,那么你不能使用子类。

public class MyHashMap<K,V> extends HashMap<K,V> { 
    public V get(K key, V default) { 
     V ret = get(key); 
     if (ret == null) { 
      return defaultValue; 
     } 
     return ret; 
    } 
} 
+5

进行额外的查找并不会造成错误,效率稍低。 (如果地图包含空值,则可能需要)。 –

+0

功能很棒!我喜欢这种形式(对不起格式不好): 'public static V mapGet(Map map,K key,V def){ final V ret = map.get(key); return ret == null? def:ret; }' –

+0

这完全不正确,因为hashmaps可以具有空值。请将@ soulcheck的答案标记为已接受:'containsKey'是在Java中执行此操作的正确方法,是的,它是冗长的:) –

1

都是有效的解决方案(虽然引入一个局部变量可能会更好...性能明智),但它不是一个好主意,在代码中随处可见这样做。考虑编写一个适配器HashMap,为您提供一个新的get()方法,允许您指定一个默认值。这是增强课堂功能的最佳方式。

0

map.get("x") == null ? true : map.get("x")

这听起来不错,但如果你需要它广泛,你可以在get()实现自己的实现来处理这个itlself

2

我估计...

Object o = map.get("x"); 
if(o == null) 
    o = BOOLEAN.TRUE; 

...几乎是最可取和最有效的方法。你只用这种方式进行一次地图查找。不幸的是,“Java”和“简洁”不适合同一句话,除非它是否定的。

+2

它并不像python字典#get(key,default_value)一样。 – soulcheck

+1

@soulcheck良好的呼叫。忘记了该映射可能包含值为null的键。不幸的是,Java没有一些方便的方法来区分“无此键”和“映射到null”的情况,就像Scala一样。如果'null'是一个不应该导致默认值的重要的可能值,那么这种方法是不正确的。你仍然需要像你所显示的那样调用'containsKey'。 –

6

OP编辑他的问题,但我会留下答案,以防万一。

,您应该使用的

map.containsKey("x") 

代替

map.get("x") != null 

测试是否映射具有关键的映射。

地图在映射中可以包含null作为有效值。

蟒蛇也​​是如此。仅仅通过测试dict [key] == None来知道某个键是否映射到某个东西是不够的。

快速试验:

d = {'a': None} 

# returns True 
d['a'] == None 

# raises KeyError 
d['b'] 

# returns 'Whatever' 
d.get('b', 'Whatever') 

所以Java相当于蟒dict.get()是

map.containsKey("x") ? map.get("x") : default_value 

如OP所述

0

我延伸地图以暴露get(String key, Boolean defaultValue)。如果不是,我会至少把三元组放在一个方法中,将get.("x")的结果推到栈上,而不是两次......类似于IfNull(map.get("x"), True)

如果你需要提供默认值,你可能对映射有一个“专门化”的用途,因此我猜这个包装类将会成为一种方式,不仅仅是这种行为,而是任何其他和未来)专门的行为/职责。

这就是我是多么想解决它......我不是面向对象的设计大师,虽然;-)

干杯。基思。

0

短,合理通用的方法来做到这一点,虽然不一定是很好的做法,将是一个辅助类和静态导入:

Helper.java

package vlad; 
import java.util.Map; 
public class Helper{  
    public static <K,V> V get(Map<K,V> m, K key, V def){ 
     V v = m.get(key); 
     return (v!=null) ? v : def; 
    } 
} 

Test.java

import java.util.*; 
import static vlad.Helper.get; 

class Test{ 

    public static void main(String[]args){ 

     Map<String, Integer> m = new HashMap<String,Integer>(); 

     m.put("forty-two", 42); 
     m.put("three", 3); 
     m.put("one", 1); 

     System.out.println(get(m,"forty-two",-1)); 
     System.out.println(get(m,"three",-1)); 
     System.out.println(get(m,"one",-1)); 
     System.out.println(get(m,"something_else",-1)); 

    } 
}