development

발견되지 않은 키의 기본값을 반환하는 HashMap?

big-blog 2020. 7. 2. 07:15
반응형

발견되지 않은 키의 기본값을 반환하는 HashMap?


HashMap세트에서 찾을 수없는 모든 키에 대해 기본값을 반환 할 수 있습니까?


[최신 정보]

다른 답변과 의견 작성자가 언급했듯이 Java 8부터 간단히 전화 할 수 있습니다 Map#getOrDefault(...).

[실물]

이 작업을 정확히 수행하는 Map 구현은 없지만 HashMap을 확장하여 직접 구현하는 것은 쉽지 않습니다.

public class DefaultHashMap<K,V> extends HashMap<K,V> {
  protected V defaultValue;
  public DefaultHashMap(V defaultValue) {
    this.defaultValue = defaultValue;
  }
  @Override
  public V get(Object k) {
    return containsKey(k) ? super.get(k) : defaultValue;
  }
}

Java 8에서는 Map.getOrDefault를 사용 하십시오 . 일치하는 키가 없으면 키를 반환하고 값을 반환합니다.


바퀴를 재발견하고 싶지 않다면 Commons의 DefaultedMap을 사용하십시오 .

Map<String, String> map = new DefaultedMap<>("[NO ENTRY FOUND]");
String surname = map.get("Surname"); 
// surname == "[NO ENTRY FOUND]"

처음에지도 작성을 담당하지 않는 경우 기존지도를 전달할 수도 있습니다.


Java 8 은 게으른 계산 값을 저장하고 맵 계약을 위반하지 않는 인터페이스에 멋진 computeIfAbsent 기본 메소드를 도입했습니다 Map.

Map<Key, Graph> map = new HashMap<>();
map.computeIfAbsent(aKey, key -> createExpensiveGraph(key));

출처 : http://blog.javabien.net/2014/02/20/loadingcache-in-java-8-without-guava/

Disclamer : 이 답변은 OP가 요청한 것과 정확히 일치하지 않지만 키 번호가 제한되어 있고 다른 값의 캐싱이 수익성이있는 경우 질문 제목과 일치하는 경우에 유용 할 수 있습니다. 메모리가 불필요하게 낭비되는 것과 같이 많은 키와 동일한 기본값으로 반대의 경우에는 사용해서는 안됩니다.


정확히 이것을 수행하는 정적 메소드를 작성할 수 없습니까?

private static <K, V> V getOrDefault(Map<K,V> map, K key, V defaultValue) {
    return map.containsKey(key) ? map.get(key) : defaultValue;
}

HashMap을 상속하는 새 클래스를 작성하고 getDefault 메소드를 추가하면됩니다. 다음은 샘플 코드입니다.

public class DefaultHashMap<K,V> extends HashMap<K,V> {
    public V getDefault(K key, V defaultValue) {
        if (containsKey(key)) {
            return get(key);
        }

        return defaultValue;
    }
}

Ed Staub가 언급 한 이유와 Map 인터페이스 계약위반하기 때문에 구현에서 get (K key) 메소드를 재정의해서는 안된다고 생각합니다 (이는 잠재적으로 찾기 어려운 결과를 초래할 수 있습니다) 버그).


사용하다:

myHashMap.getOrDefault(key, defaultValue);

기본적으로이 작업을 수행합니다. 를 반환합니다 null.


LazyMap이 매우 유용 하다는 것을 알았 습니다.

맵에 존재하지 않는 키로 get (Object) 메소드를 호출하면 팩토리가 오브젝트를 작성하는 데 사용됩니다. 생성 된 객체는 요청 된 키를 사용하여 맵에 추가됩니다.

이를 통해 다음과 같은 작업을 수행 할 수 있습니다.

    Map<String, AtomicInteger> map = LazyMap.lazyMap(new HashMap<>(), ()->new AtomicInteger(0));
    map.get(notExistingKey).incrementAndGet();

The call to get creates a default value for the given key. You specify how to create the default value with the factory argument to LazyMap.lazyMap(map, factory). In the example above, the map is initialized to a new AtomicInteger with value 0.


On java 8+

Map.getOrDefault(Object key,V defaultValue)

Not directly, but you can extend the class to modify its get method. Here is a ready to use example: http://www.java2s.com/Code/Java/Collections-Data-Structure/ExtendedVersionofjavautilHashMapthatprovidesanextendedgetmethodaccpetingadefaultvalue.htm


/**
 * Extension of TreeMap to provide default value getter/creator.
 * 
 * NOTE: This class performs no null key or value checking.
 * 
 * @author N David Brown
 *
 * @param <K>   Key type
 * @param <V>   Value type
 */
public abstract class Hash<K, V> extends TreeMap<K, V> {

    private static final long serialVersionUID = 1905150272531272505L;

    /**
     * Same as {@link #get(Object)} but first stores result of
     * {@link #create(Object)} under given key if key doesn't exist.
     * 
     * @param k
     * @return
     */
    public V getOrCreate(final K k) {
        V v = get(k);
        if (v == null) {
            v = create(k);
            put(k, v);
        }
        return v;
    }

    /**
     * Same as {@link #get(Object)} but returns specified default value
     * if key doesn't exist. Note that default value isn't automatically
     * stored under the given key.
     * 
     * @param k
     * @param _default
     * @return
     */
    public V getDefault(final K k, final V _default) {
        V v = get(k);
        return v == null ? _default : v;
    }

    /**
     * Creates a default value for the specified key.
     * 
     * @param k
     * @return
     */
    abstract protected V create(final K k);
}

Example Usage:

protected class HashList extends Hash<String, ArrayList<String>> {
    private static final long serialVersionUID = 6658900478219817746L;

    @Override
        public ArrayList<Short> create(Short key) {
            return new ArrayList<Short>();
        }
}

final HashList haystack = new HashList();
final String needle = "hide and";
haystack.getOrCreate(needle).add("seek")
System.out.println(haystack.get(needle).get(0));

I needed to read the results returned from a server in JSON where I couldn't guarantee the fields would be present. I'm using class org.json.simple.JSONObject which is derived from HashMap. Here are some helper functions I employed:

public static String getString( final JSONObject response, 
                                final String key ) 
{ return getString( response, key, "" ); }  
public static String getString( final JSONObject response, 
                                final String key, final String defVal ) 
{ return response.containsKey( key ) ? (String)response.get( key ) : defVal; }

public static long getLong( final JSONObject response, 
                            final String key ) 
{ return getLong( response, key, 0 ); } 
public static long getLong( final JSONObject response, 
                            final String key, final long defVal ) 
{ return response.containsKey( key ) ? (long)response.get( key ) : defVal; }

public static float getFloat( final JSONObject response, 
                              final String key ) 
{ return getFloat( response, key, 0.0f ); } 
public static float getFloat( final JSONObject response, 
                              final String key, final float defVal ) 
{ return response.containsKey( key ) ? (float)response.get( key ) : defVal; }

public static List<JSONObject> getList( final JSONObject response, 
                                        final String key ) 
{ return getList( response, key, new ArrayList<JSONObject>() ); }   
public static List<JSONObject> getList( final JSONObject response, 
                                        final String key, final List<JSONObject> defVal ) { 
    try { return response.containsKey( key ) ? (List<JSONObject>) response.get( key ) : defVal; }
    catch( ClassCastException e ) { return defVal; }
}   

In mixed Java/Kotlin projects also consider Kotlin's Map.withDefault.

참고URL : https://stackoverflow.com/questions/7519339/hashmap-to-return-default-value-for-non-found-keys

반응형