Guava memberi kami metode pabrik yang bagus untuk jenis Java, seperti Maps.newHashMap()
.
Tetapi apakah ada juga pembuat untuk java Maps?
HashMap<String,Integer> m = Maps.BuildHashMap.
put("a",1).
put("b",2).
build();
Guava memberi kami metode pabrik yang bagus untuk jenis Java, seperti Maps.newHashMap()
.
Tetapi apakah ada juga pembuat untuk java Maps?
HashMap<String,Integer> m = Maps.BuildHashMap.
put("a",1).
put("b",2).
build();
Jawaban:
Karena Map
antarmuka Java 9 berisi:
Map.of(k1,v1, k2,v2, ..)
Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ..)
. Batasan dari metode pabrik tersebut adalah:
null
s sebagai kunci dan / atau nilai (jika Anda perlu menyimpan null, lihat jawaban lain)Jika kita membutuhkan peta yang dapat berubah (seperti HashMap) kita dapat menggunakan copy-konstruktornya dan membiarkannya menyalin konten peta yang dibuat melaluiMap.of(..)
Map<Integer, String> map = new HashMap<>( Map.of(1,"a", 2,"b", 3,"c") );
null
nilai, yang bisa menjadi masalah bergantung pada kasus penggunaan.
Map.of(k1,v1, k2,v2, ...)
dapat digunakan dengan aman saat kita tidak memiliki banyak nilai. Untuk jumlah nilai yang lebih besar Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ...)
memberi kami kode yang lebih mudah dibaca yang lebih sedikit rawan kesalahan (kecuali saya salah paham).
Tidak ada hal seperti itu untuk HashMaps, tetapi Anda dapat membuat ImmutableMap dengan pembuat:
final Map<String, Integer> m = ImmutableMap.<String, Integer>builder().
put("a", 1).
put("b", 2).
build();
Dan jika Anda membutuhkan peta yang bisa berubah, Anda bisa memasukkannya ke konstruktor HashMap.
final Map<String, Integer> m = Maps.newHashMap(
ImmutableMap.<String, Integer>builder().
put("a", 1).
put("b", 2).
build());
ImmutableMap
tidak mendukung null
nilai-nilai. Jadi, ada batasan dari pendekatan ini: Anda tidak dapat menetapkan nilai di HashMap
to null
.
new HashMap
konstruktor Java daripada Maps.newHashMap
metode statis ?
Bukan pembuatnya, tapi menggunakan penginisialisasi:
Map<String, String> map = new HashMap<String, String>() {{
put("a", "1");
put("b", "2");
}};
map instanceof HashMap
salah? Sepertinya ide yang tidak terlalu bagus.
map.getClass()==HashMap.class
akan mengembalikan false. Tapi itu tes bodoh. HashMap.class.isInstance(map)
harus lebih disukai, dan itu akan menjadi kenyataan.
Ini mirip dengan jawaban yang diterima, tetapi sedikit lebih bersih, menurut saya:
ImmutableMap.of("key1", val1, "key2", val2, "key3", val3);
Ada beberapa variasi dari metode di atas, dan metode ini bagus untuk membuat peta yang statis, tidak berubah, dan tidak berubah.
Ini yang sangat sederhana ...
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);
}
}
kemudian
import static FluentHashMap.map;
HashMap<String, Integer> m = map("a", 1).with("b", 2);
Lihat https://gist.github.com/culmat/a3bcc646fa4401641ac6eb01f3719065
Pembuat peta sederhana itu mudah untuk ditulis:
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());
}
}
}
Kamu bisa memakai:
HashMap<String,Integer> m = Maps.newHashMap(
ImmutableMap.of("a",1,"b",2)
);
Ini tidak berkelas dan mudah dibaca, tetapi berhasil.
Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 2);
lebih baik?
HashMap
bisa berubah; tidak perlu seorang pembangun.
Map<String, Integer> map = Maps.newHashMap();
map.put("a", 1);
map.put("b", 2);
ImmutableSet
. Jika Anda benar-benar ingin ini bisa berubah, Anda bisa menginisialisasinya di konstruktor atau blok penginisialisasi instance atau blok penginisialisasi statis jika itu bidang statis.
ImmutableMap
sana dengan jelas.
{{init();}}
(bukan di konstruktor, karena konstruktor lain mungkin melupakannya). Dan itu bagus karena itu semacam aksi atom. Jika peta mudah berubah, kemudian menginisialisasi dengan pembangun memastikan peta itu selalu baik null
atau dalam keadaan akhir, tidak pernah terisi setengah.
Anda dapat menggunakan API yang lancar di Koleksi Eclipse :
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);
Berikut adalah blog dengan lebih detail dan contoh.
Catatan: Saya seorang pelaku untuk Koleksi Eclipse.
Saya memiliki persyaratan serupa beberapa waktu lalu. Ini tidak ada hubungannya dengan Guava tetapi Anda dapat melakukan hal seperti ini untuk dapat membangun dengan rapi Map
menggunakan pembangun yang lancar.
Buat kelas dasar yang memperluas 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;
}
}
Kemudian buat pembangun yang fasih dengan metode yang sesuai dengan kebutuhan Anda:
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...
}
Anda kemudian dapat menerapkannya seperti ini:
ValueMap map = new ValueMap()
.withValue("key 1", "value 1")
.withValue("key 2", "value 2")
.withValue("key 3", "value 3")
Ini adalah sesuatu yang selalu saya inginkan, terutama saat menyiapkan perlengkapan tes. Akhirnya, saya memutuskan untuk menulis pembuat fasih sederhana milik saya yang dapat membangun implementasi Peta apa pun - https://gist.github.com/samshu/b471f5a2925fa9d9b718795d8bbdfe42#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;
}
Ini yang saya tulis
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);
}
}
Anda menggunakannya seperti ini:
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();
Menggunakan java 8:
Ini adalah pendekatan Java-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);
}
}
Cara Penggunaan:
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)
);
Underscore-java dapat membuat peta hash.
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}]}