เป็นไปได้หรือไม่ที่จะHashMap
ส่งคืนค่าเริ่มต้นสำหรับคีย์ทั้งหมดที่ไม่พบในชุด
เป็นไปได้หรือไม่ที่จะHashMap
ส่งคืนค่าเริ่มต้นสำหรับคีย์ทั้งหมดที่ไม่พบในชุด
คำตอบ:
[Update]
เท่าที่สังเกตจากคำตอบอื่น ๆ และการแสดงความคิดเห็นเป็นของ Java 8 Map#getOrDefault(...)
คุณก็สามารถโทร
[ต้นฉบับ]
ไม่มีการใช้งานแผนที่ที่ทำสิ่งนี้ได้อย่างแน่นอน แต่การใช้งานของคุณเองด้วยการขยาย 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;
}
}
(v == null)
เป็นเป็น(v == null && !this.containsKey(k))
ในกรณีที่ต้องการเพิ่มnull
มูลค่า ฉันรู้ว่านี่เป็นเพียงแค่มุม แต่ผู้เขียนอาจพบเจอ
!this.containsValue(null)
ผมสังเกตเห็นว่าที่คุณใช้ !this.containsKey(k)
นี้เป็นอย่างละเอียดที่แตกต่างจาก containsValue
วิธีการแก้ปัญหาจะล้มเหลวถ้าบางคนอื่น ๆnull
ที่สำคัญได้รับมอบหมายค่าอย่างชัดเจน ตัวอย่างเช่น: map = new HashMap(); map.put(k1, null); V v = map.get(k2);
ในกรณีนี้v
จะยังคงnull
ถูกต้องหรือไม่
getOrDefault
ดีมาก แต่ต้องการนิยามเริ่มต้นทุกครั้งที่เข้าถึงแผนที่ การกำหนดค่าเริ่มต้นเพียงครั้งเดียวก็จะมีประโยชน์ในการอ่านได้เมื่อสร้างแผนที่แบบคงที่ของค่า
private static String get(Map map, String s) { return map.getOrDefault(s, "Error"); }
ใช้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;
}
}
ฉันคิดว่าคุณไม่ควรลบล้างวิธี get (K key) ในการติดตั้งของคุณเนื่องจากเหตุผลที่ระบุโดย Ed Staub ในความคิดเห็นของเขาและเพราะคุณจะทำสัญญากับส่วนต่อประสานของ Map (สิ่งนี้อาจทำให้ยากต่อการค้นหา ข้อบกพร่อง)
get
วิธีนี้ ในทางกลับกัน - โซลูชันของคุณไม่อนุญาตให้ใช้คลาสผ่านอินเทอร์เฟซซึ่งอาจเป็นกรณี
ใช้:
myHashMap.getOrDefault(key, defaultValue);
บน java 8+
Map.getOrDefault(Object key,V defaultValue)
ฉันพบว่าLazyMapมีประโยชน์มาก
เมื่อมีการเรียกใช้เมธอด get (Object) ด้วยรหัสที่ไม่มีอยู่ในแผนที่โรงงานจะใช้ในการสร้างวัตถุ วัตถุที่สร้างจะถูกเพิ่มลงในแผนที่โดยใช้คีย์ที่ร้องขอ
สิ่งนี้อนุญาตให้คุณทำสิ่งนี้:
Map<String, AtomicInteger> map = LazyMap.lazyMap(new HashMap<>(), ()->new AtomicInteger(0));
map.get(notExistingKey).incrementAndGet();
การเรียกเพื่อget
สร้างค่าเริ่มต้นสำหรับคีย์ที่กำหนด LazyMap.lazyMap(map, factory)
คุณสามารถระบุวิธีการสร้างค่าเริ่มต้นที่มีการโต้แย้งโรงงาน ในตัวอย่างด้านบนแผนที่จะเริ่มต้นใหม่AtomicInteger
ด้วยค่า 0
ไม่ได้โดยตรง แต่คุณสามารถขยายชั้นเรียนเพื่อปรับเปลี่ยนวิธีการรับ นี่คือตัวอย่างที่พร้อมใช้งาน: 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);
}
ตัวอย่างการใช้งาน:
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));
ฉันจำเป็นต้องอ่านผลลัพธ์ที่ส่งคืนจากเซิร์ฟเวอร์ใน JSON ซึ่งฉันไม่สามารถรับประกันได้ว่าจะมีฟิลด์ต่างๆ ฉันใช้ class org.json.simple.JSONObject ซึ่งมาจาก HashMap นี่คือฟังก์ชั่นตัวช่วยที่ฉันใช้:
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; }
}
ในโปรเจ็กต์ Java / Kotlin แบบผสมให้พิจารณาMap.withDefaultของ Kotlin ด้วย