Pertanyaan Bagaimana saya bisa menginisialisasi Peta statis?


Bagaimana Anda akan menginisialisasi Peta statis di Java?

Metode satu: initialiser statis
Metode dua: contoh initialiser (subkelas anonim) atau beberapa metode lain?

Apa pro dan kontra dari masing-masing?

Berikut ini contoh yang menggambarkan dua metode:

import java.util.HashMap;
import java.util.Map;

public class Test {
    private static final Map<Integer, String> myMap = new HashMap<Integer, String>();
    static {
        myMap.put(1, "one");
        myMap.put(2, "two");
    }

    private static final Map<Integer, String> myMap2 = new HashMap<Integer, String>(){
        {
            put(1, "one");
            put(2, "two");
        }
    };
}

930
2018-02-03 15:41


asal


Jawaban:


Inisitor instance hanya gula sintaksis dalam kasus ini, kan? Saya tidak mengerti mengapa Anda membutuhkan kelas anonim tambahan hanya untuk menginisialisasi. Dan itu tidak akan berhasil jika kelas yang dibuat adalah final.

Anda dapat membuat peta abadi menggunakan inisialisasi statis juga:

public class Test {
    private static final Map<Integer, String> myMap;
    static {
        Map<Integer, String> aMap = ....;
        aMap.put(1, "one");
        aMap.put(2, "two");
        myMap = Collections.unmodifiableMap(aMap);
    }
}

945
2017-08-31 13:58



saya suka Jambu biji cara menginisialisasi peta statis dan tidak berubah:

static final Map<Integer, String> MY_MAP = ImmutableMap.of(
    1, "one",
    2, "two"
);

Seperti yang Anda lihat, itu sangat singkat (karena metode pabrik yang nyaman di ImmutableMap).

Jika Anda ingin peta memiliki lebih dari 5 entri, Anda tidak lagi dapat menggunakannya ImmutableMap.of(). Sebaliknya, cobalah ImmutableMap.builder() sepanjang garis ini:

static final Map<Integer, String> MY_MAP = ImmutableMap.<Integer, String>builder()
    .put(1, "one")
    .put(2, "two")
    // ... 
    .put(15, "fifteen")
    .build();

Untuk mempelajari lebih lanjut tentang manfaat utilitas koleksi abadi Guava, lihat Koleksi yang Tidak Bisa Dijelaskan dalam Panduan Pengguna Guava.

(A subset dari) Guava dulu disebut Koleksi Google. Jika Anda tidak menggunakan pustaka ini di proyek Java Anda, saya dengan kuat sarankan untuk mencobanya! Jambu biji dengan cepat menjadi salah satu lib pihak ke-3 gratis yang paling populer dan berguna untuk Java, sebagai sesama pengguna SO setuju. (Jika Anda baru mengenalnya, ada beberapa sumber belajar yang bagus di balik tautan itu.)


Perbarui (2015): Adapun Java 8, baik, saya masih akan menggunakan pendekatan Jambu karena lebih bersih dari yang lain. Jika Anda tidak ingin ketergantungan Guava, pertimbangkan a metode init tua biasa. Peretasan dengan array dua dimensi dan Streaming API cukup jelek jika Anda bertanya kepada saya, dan menjadi lebih jelek jika Anda perlu membuat Peta yang kunci dan nilainya tidak memiliki tipe yang sama (seperti Map<Integer, String> dalam pertanyaan).

Adapun masa depan Guava secara umum, berkaitan dengan Java 8, Louis Wasserman kata ini kembali pada tahun 2014, dan [memperbarui] pada tahun 2016 diumumkan bahwa Guava 21 akan membutuhkan dan benar mendukung Java 8.


Perbarui (2016): Sebagai Tagir Valeev menunjukkan, Java 9 akhirnya akan membuat ini bersih untuk tidak menggunakan apa-apa selain JDK murni, dengan menambahkan metode pabrik kenyamanan untuk koleksi:

static final Map<Integer, String> MY_MAP = Map.of(
    1, "one", 
    2, "two"
);

370
2018-02-03 21:40



Saya akan menggunakan:

public class Test {
    private static final Map<Integer, String> MY_MAP = createMap();

    private static Map<Integer, String> createMap() {
        Map<Integer, String> result = new HashMap<Integer, String>();
        result.put(1, "one");
        result.put(2, "two");
        return Collections.unmodifiableMap(result);
    }
}
  1. itu menghindari kelas anonim, yang saya pribadi anggap sebagai gaya buruk, dan hindari
  2. itu membuat pembuatan peta lebih eksplisit
  3. itu membuat peta tidak bisa dimodifikasi
  4. karena MY_MAP konstan, saya akan menamakannya seperti konstan

160
2017-07-15 21:29



Java 5 menyediakan sintaks yang lebih ringkas ini:

static final Map<String , String> FLAVORS = new HashMap<String , String>() {{
    put("Up",    "Down");
    put("Charm", "Strange");
    put("Top",   "Bottom");
}};

157
2018-02-03 15:44



Salah satu keunggulan metode kedua adalah Anda bisa membungkusnya dengan Collections.unmodifiableMap() untuk menjamin tidak ada yang akan memperbarui koleksi nanti:

private static final Map<Integer, String> CONSTANT_MAP = 
    Collections.unmodifiableMap(new HashMap<Integer, String>() {{ 
        put(1, "one");
        put(2, "two");
    }});

 // later on...

 CONSTANT_MAP.put(3, "three"); // going to throw an exception!

80
2017-09-14 00:44



Berikut adalah penginisialisasi peta statis statis 8 baris:

private static final Map<String, String> EXTENSION_TO_MIMETYPE =
    Arrays.stream(new String[][] {
        { "txt", "text/plain" }, 
        { "html", "text/html" }, 
        { "js", "application/javascript" },
        { "css", "text/css" },
        { "xml", "application/xml" },
        { "png", "image/png" }, 
        { "gif", "image/gif" }, 
        { "jpg", "image/jpeg" },
        { "jpeg", "image/jpeg" }, 
        { "svg", "image/svg+xml" },
    }).collect(Collectors.toMap(kv -> kv[0], kv -> kv[1]));

Edit: untuk menginisialisasi a Map<Integer, String> seperti dalam pertanyaan, Anda memerlukan sesuatu seperti ini:

static final Map<Integer, String> MY_MAP = Arrays.stream(new Object[][]{
        {1, "one"},
        {2, "two"},
}).collect(Collectors.toMap(kv -> (Integer) kv[0], kv -> (String) kv[1]));

Edit (2): Ada yang lebih baik, versi campuran-jenis-mampu oleh i_am_zero yang menggunakan aliran new SimpleEntry<>(k, v) panggilan. Lihat jawabannya: https://stackoverflow.com/a/37384773/3950982


52
2017-12-29 10:07



Di Java 9:

private static final Map<Integer, String> MY_MAP = Map.of(1, "one", 2, "two");

Lihat JEP 269 untuk detailnya. JDK 9 tercapai ketersediaan umum pada bulan September 2017.


39
2017-12-18 23:10



Dengan Koleksi Eclipse (dahulu Koleksi GS), semua hal berikut akan berfungsi:

import java.util.Map;

import org.eclipse.collections.api.map.ImmutableMap;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.impl.factory.Maps;

public class StaticMapsTest
{
    private static final Map<Integer, String> MAP =
        Maps.mutable.with(1, "one", 2, "two");

    private static final MutableMap<Integer, String> MUTABLE_MAP =
       Maps.mutable.with(1, "one", 2, "two");


    private static final MutableMap<Integer, String> UNMODIFIABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").asUnmodifiable();


    private static final MutableMap<Integer, String> SYNCHRONIZED_MAP =
        Maps.mutable.with(1, "one", 2, "two").asSynchronized();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").toImmutable();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP2 =
        Maps.immutable.with(1, "one", 2, "two");
}

Anda juga dapat secara statis menginisialisasi peta primitif dengan Eclipse Collections.

import org.eclipse.collections.api.map.primitive.ImmutableIntObjectMap;
import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
import org.eclipse.collections.impl.factory.primitive.IntObjectMaps;

public class StaticPrimitiveMapsTest
{
    private static final MutableIntObjectMap<String> MUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two");

    private static final MutableIntObjectMap<String> UNMODIFIABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asUnmodifiable();

    private static final MutableIntObjectMap<String> SYNCHRONIZED_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asSynchronized();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .toImmutable();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP2 =
            IntObjectMaps.immutable.<String>empty()
                    .newWithKeyValue(1, "one")
                    .newWithKeyValue(2, "two");
} 

catatan: Saya seorang committer untuk Eclipse Collections


27
2018-02-03 15:55



Saya tidak akan pernah membuat subkelas anonim dalam situasi ini. Inisialisasi statis bekerja dengan baik, jika Anda ingin membuat peta tidak dapat dimodifikasi misalnya:

private static final Map<Integer, String> MY_MAP;
static
{
    Map<Integer, String>tempMap = new HashMap<Integer, String>();
    tempMap.put(1, "one");
    tempMap.put(2, "two");
    MY_MAP = Collections.unmodifiableMap(tempMap);
}

24
2018-02-03 21:33



Mungkin menarik untuk dicoba Koleksi Google, mis. video yang mereka miliki di halaman mereka. Mereka menyediakan berbagai cara untuk menginisialisasi peta dan set, dan menyediakan koleksi yang tidak berubah juga.

Pembaruan: Perpustakaan ini sekarang bernama Jambu biji.


14
2017-09-19 08:48