Apakah mungkin mendapatkan elemen dari HashMap berdasarkan posisinya?

99

Bagaimana cara mengambil elemen dari HashMap berdasarkan posisinya, apakah mungkin sama sekali?

Eugene
sumber
11
Apa yang Anda maksud dengan "posisi"? HashMaps tidak diurutkan, jadi mereka tidak memiliki gagasan biasa tentang "posisi" yang akan Anda dapatkan dengan sesuatu seperti Vektor.
Mat
1
Apakah yang Anda maksud dengan urutan penyisipannya atau pemesanan lainnya?
Mark Elliot

Jawaban:

94

HashMaps tidak mempertahankan pemesanan:

Kelas ini tidak menjamin urutan peta; Secara khusus, ini tidak menjamin bahwa pesanan akan tetap konstan dari waktu ke waktu.

Lihat LinkedHashMap , yang menjamin urutan iterasi yang dapat diprediksi.

Wayne
sumber
16
Ini tidak benar-benar menjawab pertanyaan itu. Jawaban lain di bawah ini lebih bermanfaat.
forresthopkinsa
6
Sehubungan dengan itu, ini mengutip dokumentasi yang secara langsung menjawab pertanyaan
Wayne
1
Bahkan jika urutannya tidak konstan dari waktu ke waktu, masih mungkin untuk mengambil salah satu anggota dengan posisi tertentu.
Pemula
Saya tidak mengikuti. Menjelaskan?
Wayne
Tautan HashMap rusak / 404.
Raf
109

Gunakan LinkedHashMap dan ketika Anda perlu mengambil berdasarkan posisi, ubah nilainya menjadi ArrayList.

LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<String,String>();
/* Populate */
linkedHashMap.put("key0","value0");
linkedHashMap.put("key1","value1");
linkedHashMap.put("key2","value2");
/* Get by position */
int pos = 1;
String value = (new ArrayList<String>(linkedHashMap.values())).get(pos);
Kulnor
sumber
2
Selalu diperlukan untuk membuat salinan kunci dari HashMap ??
Richard
ini akan membuat objek ArrayList baru setiap kali kami mengambil nilai, yang menyebabkan kebocoran memori
NullByte08
48

Jika Anda ingin mempertahankan urutan penambahan elemen ke peta, gunakan LinkedHashMapsebagai lawan hanya HashMap.

Berikut adalah pendekatan yang memungkinkan Anda mendapatkan nilai dengan indeksnya di peta:

public Object getElementByIndex(LinkedHashMap map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
}
Syd Lambert
sumber
1
Paling sederhana saya harus mengatakan ... Alih-alih mengubah setiap hal, Anda hanya menggunakan keyset. Luar biasa
kirtan403
19

Jika Anda, karena alasan tertentu, harus tetap menggunakan hashMap, Anda dapat mengonversi keySet ke array dan mengindeks kunci dalam array untuk mendapatkan nilai di peta seperti ini:

Object[] keys = map.keySet().toArray();

Anda kemudian dapat mengakses peta seperti:

map.get(keys[i]);
theNoble247
sumber
Perhatikan bahwa arr [i] harus diubah menjadi: keys [i]
Mohsen Abasi
Oke, saya memiliki Strings sebagai kunci peta, untuk mendapatkan salah satunya, bagian kedua adalah:String myKey = keys[i].toString();
Orici
12

Penggunaan LinkedHashMap:

Tabel hash dan implementasi daftar tertaut dari antarmuka Peta, dengan urutan iterasi yang dapat diprediksi. Implementasi ini berbeda dari HashMap karena mempertahankan daftar tertaut ganda yang berjalan melalui semua entri.

ilalex
sumber
27
yang akan mempertahankan pesanan, tetapi Anda masih tidak dapat mengakses item dengan indeksnya. Anda harus mengulang
Bozho
tautan ini ke versi lama API. Saya menyarankan untuk menautkan ke Java 6 atau 7 API.
jzd
6

Gunakan LinkedHashMap dan gunakan fungsi ini.

private LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>();

Definisikan seperti ini dan.

private Entry getEntry(int id){
        Iterator iterator = map.entrySet().iterator();
        int n = 0;
        while(iterator.hasNext()){
            Entry entry = (Entry) iterator.next();
            if(n == id){
                return entry;
            }
            n ++;
        }
        return null;
    }

Fungsi ini dapat mengembalikan entri yang dipilih.

Jeff Lee
sumber
3

Saya berasumsi dengan 'posisi' Anda mengacu pada urutan di mana Anda telah memasukkan elemen ke dalam HashMap. Dalam hal ini Anda ingin menggunakan LinkedHashMap. Namun LinkedHashMap tidak menawarkan metode pengakses; Anda perlu menulis satu suka

public Object getElementAt(LinkedHashMap map, int index) {
    for (Map.Entry entry : map.entrySet()) {
        if (index-- == 0) {
            return entry.value();
        }
    }
    return null;
}
homebrew
sumber
3

Pendekatan kerja lainnya adalah mengubah nilai peta menjadi array dan kemudian mengambil elemen pada indeks. Uji coba 100 000 elemen dengan pencarian indeks di LinkedHashMap dari 100 000 objek menggunakan pendekatan berikut menghasilkan hasil sebagai berikut:

//My answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.values().toArray(new Particle[map.values().size()])[index];
} //68 965 ms

//Syd Lambert's answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
} //80 700 ms

Secara keseluruhan, mengambil elemen dengan indeks dari LinkedHashMap tampaknya merupakan operasi yang cukup berat.

pengguna3738243
sumber
2

HashMap - dan struktur data yang mendasarinya - tabel hash, tidak memiliki gagasan tentang posisi. Tidak seperti LinkedList atau Vector, kunci masukan diubah menjadi 'keranjang' tempat nilai disimpan. Bucket ini tidak dipesan dengan cara yang masuk akal di luar antarmuka HashMap dan oleh karena itu, item yang Anda masukkan ke HashMap tidak berurutan seperti yang Anda harapkan dengan struktur data lainnya.

dfb
sumber
2

HashMap tidak memiliki konsep posisi sehingga tidak ada cara untuk mendapatkan objek berdasarkan posisi. Objek di Maps diatur dan didapatkan dengan kunci.

Robby Pond
sumber
2

Anda dapat menggunakan kode di bawah ini untuk mendapatkan kunci: String [] keys = (String[]) item.keySet().toArray(new String[0]);

dan dapatkan objek atau daftar yang dimasukkan ke dalam HashMap dengan kunci item ini seperti ini: item.get(keys[position]);

mahsa k
sumber
2

Secara default, java LinkedHasMap tidak mendukung untuk mendapatkan nilai berdasarkan posisi. Jadi saya sarankan pergi dengan disesuaikanIndexedLinkedHashMap

public class IndexedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    private ArrayList<K> keysList = new ArrayList<>();

    public void add(K key, V val) {
        super.put(key, val);
        keysList.add(key);
    }

    public void update(K key, V val) {
        super.put(key, val);
    }

    public void removeItemByKey(K key) {
        super.remove(key);
        keysList.remove(key);
    }

    public void removeItemByIndex(int index) {
        super.remove(keysList.get(index));
        keysList.remove(index);
    }

    public V getItemByIndex(int i) {
        return (V) super.get(keysList.get(i));
    }

    public int getIndexByKey(K key) {
        return keysList.indexOf(key);
    }
}

Kemudian Anda dapat menggunakan LinkedHasMap yang disesuaikan ini sebagai

IndexedLinkedHashMap<String,UserModel> indexedLinkedHashMap=new IndexedLinkedHashMap<>();

UNTUK menambahkan Nilai

indexedLinkedHashMap.add("key1",UserModel);

Untuk mendapatkan nilai berdasarkan indeks

indexedLinkedHashMap.getItemByIndex(position);
Vikram Kodag
sumber
1

HashMaps tidak mengizinkan akses berdasarkan posisi, ia hanya mengetahui tentang kode hash dan dan dapat mengambil nilainya jika dapat menghitung kode hash dari kunci tersebut. TreeMaps memiliki gagasan tentang pengurutan. Peta Linkedhas mempertahankan urutan mereka memasuki peta.

fastcodejava.dll
sumber
0

Anda dapat mencoba menerapkan sesuatu seperti itu, lihat:

Map<String, Integer> map = new LinkedHashMap<String, Integer>();
map.put("juan", 2);
map.put("pedro", 3);
map.put("pablo", 5);
map.put("iphoncio",9)

List<String> indexes = new ArrayList<String>(map.keySet()); // <== Parse

System.out.println(indexes.indexOf("juan"));     // ==> 0
System.out.println(indexes.indexOf("iphoncio"));      // ==> 3

Saya harap ini berhasil untuk Anda.

Francisco Javier Ocampo
sumber