अमरूद हमें जावा प्रकारों के लिए महान कारखाने के तरीके प्रदान करता है, जैसे कि Maps.newHashMap()
।
लेकिन क्या जावा मैप्स के लिए बिल्डर भी हैं?
HashMap<String,Integer> m = Maps.BuildHashMap.
put("a",1).
put("b",2).
build();
अमरूद हमें जावा प्रकारों के लिए महान कारखाने के तरीके प्रदान करता है, जैसे कि Maps.newHashMap()
।
लेकिन क्या जावा मैप्स के लिए बिल्डर भी हैं?
HashMap<String,Integer> m = Maps.BuildHashMap.
put("a",1).
put("b",2).
build();
जवाबों:
चूंकि जावा 9 Map
इंटरफ़ेस में शामिल है:
Map.of(k1,v1, k2,v2, ..)
Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ..)
। उन कारखाने के तरीकों की सीमाएँ हैं:
null
कुंजी और / या मान के रूप में पकड़ नहीं कर सकते हैं (यदि आपको नल को संग्रहीत करने की आवश्यकता है, तो अन्य उत्तरों पर एक नज़र डालें)अगर हमें परस्पर मानचित्र (जैसे हाशप) की आवश्यकता है, तो हम इसके कॉपी-कंस्ट्रक्टर का उपयोग कर सकते हैं और इसके माध्यम से बनाए गए नक्शे की सामग्री की प्रतिलिपि बना सकते हैंMap.of(..)
Map<Integer, String> map = new HashMap<>( Map.of(1,"a", 2,"b", 3,"c") );
null
मूल्यों की अनुमति नहीं देती हैं, जो उपयोग के मामले के आधार पर एक समस्या हो सकती है।
Map.of(k1,v1, k2,v2, ...)
का उपयोग तब सुरक्षित रूप से किया जा सकता है जब हमारे पास कई मूल्य नहीं होते हैं। मूल्यों की बड़ी मात्रा के लिए Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ...)
हमें अधिक पठनीय कोड मिलता है जो कम त्रुटि वाला है (जब तक कि मैंने आपको गलत नहीं समझा)।
HashMaps के लिए ऐसी कोई बात नहीं है, लेकिन आप एक बिल्डर के साथ एक ImmutableMap बना सकते हैं:
final Map<String, Integer> m = ImmutableMap.<String, Integer>builder().
put("a", 1).
put("b", 2).
build();
और अगर आपको एक परिवर्तनशील मानचित्र की आवश्यकता है, तो आप बस उसे HashMap निर्माता को खिला सकते हैं।
final Map<String, Integer> m = Maps.newHashMap(
ImmutableMap.<String, Integer>builder().
put("a", 1).
put("b", 2).
build());
ImmutableMap
null
मूल्यों का समर्थन नहीं करता है। तो वहाँ इस दृष्टिकोण की सीमा है: यदि आप अपने में निर्धारित नहीं कर सकते मूल्यों HashMap
को null
।
new HashMap
स्थैतिक Maps.newHashMap
विधि के बजाय जावा कंस्ट्रक्टर का उपयोग करने में कुछ गड़बड़ है ?
काफी बिल्डर नहीं है, लेकिन एक शुरुआती का उपयोग कर:
Map<String, String> map = new HashMap<String, String>() {{
put("a", "1");
put("b", "2");
}};
map instanceof HashMap
गलत नहीं होगा ? एक महान विचार नहीं लगता है।
map.getClass()==HashMap.class
झूठे लौटेगा लेकिन यह एक बेवकूफ परीक्षण है। HashMap.class.isInstance(map)
पसंद किया जाना चाहिए, और यह सच हो जाएगा।
यह स्वीकृत उत्तर के समान है, लेकिन मेरे विचार में थोड़ा साफ है:
ImmutableMap.of("key1", val1, "key2", val2, "key3", val3);
उपरोक्त विधि के कई रूप हैं, और वे स्थिर, अपरिवर्तनीय, अपरिवर्तनीय मानचित्र बनाने के लिए महान हैं।
यहाँ एक बहुत ही सरल है ...
public class FluentHashMap<K, V> extends java.util.HashMap<K, V> {
public FluentHashMap<K, V> with(K key, V value) {
put(key, value);
return this;
}
public static <K, V> FluentHashMap<K, V> map(K key, V value) {
return new FluentHashMap<K, V>().with(key, value);
}
}
फिर
import static FluentHashMap.map;
HashMap<String, Integer> m = map("a", 1).with("b", 2);
Https://gist.github.com/culmat/a3bcc646fa4401641ac6eb01f3719065 देखें
एक साधारण नक्शा बिल्डर लिखने के लिए तुच्छ है:
public class Maps {
public static <Q,W> MapWrapper<Q,W> map(Q q, W w) {
return new MapWrapper<Q, W>(q, w);
}
public static final class MapWrapper<Q,W> {
private final HashMap<Q,W> map;
public MapWrapper(Q q, W w) {
map = new HashMap<Q, W>();
map.put(q, w);
}
public MapWrapper<Q,W> map(Q q, W w) {
map.put(q, w);
return this;
}
public Map<Q,W> getMap() {
return map;
}
}
public static void main(String[] args) {
Map<String, Integer> map = Maps.map("one", 1).map("two", 2).map("three", 3).getMap();
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
आप उपयोग कर सकते हैं:
HashMap<String,Integer> m = Maps.newHashMap(
ImmutableMap.of("a",1,"b",2)
);
यह उत्तम दर्जे का और पठनीय नहीं है, लेकिन यह काम करता है।
Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 2);
, बेहतर है?
HashMap
पारस्परिक है; बिल्डर की कोई आवश्यकता नहीं है।
Map<String, Integer> map = Maps.newHashMap();
map.put("a", 1);
map.put("b", 2);
ImmutableSet
। यदि आप वास्तव में इसे बदलना चाहते हैं, तो आप इसे कंस्ट्रक्टर या उदाहरण इनिशियलज़र ब्लॉक या एक स्टैटिक इनिशियलाइज़र ब्लॉक में इनिशियलाइज़ कर सकते हैं यदि यह एक स्थिर क्षेत्र है।
ImmutableMap
वहाँ स्पष्ट रूप से कहा जाना चाहिए था ।
{{init();}}
(निर्माता में नहीं, क्योंकि अन्य निर्माता इसे भूल सकता है) में tucked । और यह अच्छा है कि यह परमाणु कार्रवाई की तरह है। यदि नक्शा अस्थिर है, तो एक बिल्डर के साथ यह सुनिश्चित करना कि यह हमेशा या तो null
अंतिम स्थिति में है, कभी भी आधा भरा नहीं है।
आप ग्रहण संग्रह में धाराप्रवाह एपीआई का उपयोग कर सकते हैं :
Map<String, Integer> map = Maps.mutable.<String, Integer>empty()
.withKeyValue("a", 1)
.withKeyValue("b", 2);
Assert.assertEquals(Maps.mutable.with("a", 1, "b", 2), map);
यहाँ एक और अधिक विस्तार और उदाहरण के साथ ब्लॉग है ।
नोट: मैं एक्लिप्स कलेक्शंस के लिए कमिट हूं।
मुझे कुछ समय पहले भी इसी तरह की आवश्यकता थी। इसका अमरूद से कोई लेना-देना नहीं है, लेकिन आप Map
धाराप्रवाह बिल्डर का उपयोग करके साफ-सफाई करने में सक्षम होने के लिए कुछ ऐसा कर सकते हैं ।
एक बेस क्लास बनाएं जो मैप का विस्तार करता है।
public class FluentHashMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 4857340227048063855L;
public FluentHashMap() {}
public FluentHashMap<K, V> delete(Object key) {
this.remove(key);
return this;
}
}
फिर अपनी आवश्यकताओं के अनुरूप विधियों के साथ धाराप्रवाह निर्माता बनाएँ:
public class ValueMap extends FluentHashMap<String, Object> {
private static final long serialVersionUID = 1L;
public ValueMap() {}
public ValueMap withValue(String key, String val) {
super.put(key, val);
return this;
}
... Add withXYZ to suit...
}
फिर आप इसे इस तरह लागू कर सकते हैं:
ValueMap map = new ValueMap()
.withValue("key 1", "value 1")
.withValue("key 2", "value 2")
.withValue("key 3", "value 3")
यह एक ऐसी चीज है जिसे मैं हमेशा से चाहता था, खासकर टेस्ट फिक्स्चर सेट करते समय। अंत में, मैंने खुद का एक सरल धाराप्रवाह बिल्डर लिखने का फैसला किया जो किसी भी मानचित्र कार्यान्वयन का निर्माण कर सकता है - https://gist.github.com/samshu/b471f5a2925fa9d9b718795d8bbdfd42#file-mapbuilder-java
/**
* @param mapClass Any {@link Map} implementation type. e.g., HashMap.class
*/
public static <K, V> MapBuilder<K, V> builder(@SuppressWarnings("rawtypes") Class<? extends Map> mapClass)
throws InstantiationException,
IllegalAccessException {
return new MapBuilder<K, V>(mapClass);
}
public MapBuilder<K, V> put(K key, V value) {
map.put(key, value);
return this;
}
public Map<K, V> build() {
return map;
}
यहाँ एक मैंने लिखा है
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
public class MapBuilder<K, V> {
private final Map<K, V> map;
/**
* Create a HashMap builder
*/
public MapBuilder() {
map = new HashMap<>();
}
/**
* Create a HashMap builder
* @param initialCapacity
*/
public MapBuilder(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
/**
* Create a Map builder
* @param mapFactory
*/
public MapBuilder(Supplier<Map<K, V>> mapFactory) {
map = mapFactory.get();
}
public MapBuilder<K, V> put(K key, V value) {
map.put(key, value);
return this;
}
public Map<K, V> build() {
return map;
}
/**
* Returns an unmodifiable Map. Strictly speaking, the Map is not immutable because any code with a reference to
* the builder could mutate it.
*
* @return
*/
public Map<K, V> buildUnmodifiable() {
return Collections.unmodifiableMap(map);
}
}
आप इसे इस तरह उपयोग करते हैं:
Map<String, Object> map = new MapBuilder<String, Object>(LinkedHashMap::new)
.put("event_type", newEvent.getType())
.put("app_package_name", newEvent.getPackageName())
.put("activity", newEvent.getActivity())
.build();
जावा 8 का उपयोग करना:
यह जावा -9 का एक दृष्टिकोण है Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ...)
public class MapUtil {
import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Stream;
private MapUtil() {}
@SafeVarargs
public static Map<String, Object> ofEntries(SimpleEntry<String, Object>... values) {
return Stream.of(values).collect(toMap(Entry::getKey, Entry::getValue));
}
public static SimpleEntry<String, Object> entry(String key, Object value) {
return new SimpleEntry<String, Object>(key, value);
}
}
कैसे इस्तेमाल करे:
import static your.package.name.MapUtil.*;
import java.util.Map;
Map<String, Object> map = ofEntries(
entry("id", 1),
entry("description", "xyz"),
entry("value", 1.05),
entry("enable", true)
);
अंडरस्कोर-जावा, हैशमैप का निर्माण कर सकता है।
Map<String, Object> value = U.objectBuilder()
.add("firstName", "John")
.add("lastName", "Smith")
.add("age", 25)
.add("address", U.arrayBuilder()
.add(U.objectBuilder()
.add("streetAddress", "21 2nd Street")
.add("city", "New York")
.add("state", "NY")
.add("postalCode", "10021")))
.add("phoneNumber", U.arrayBuilder()
.add(U.objectBuilder()
.add("type", "home")
.add("number", "212 555-1234"))
.add(U.objectBuilder()
.add("type", "fax")
.add("number", "646 555-4567")))
.build();
// {firstName=John, lastName=Smith, age=25, address=[{streetAddress=21 2nd Street,
// city=New York, state=NY, postalCode=10021}], phoneNumber=[{type=home, number=212 555-1234},
// {type=fax, number=646 555-4567}]}