cara mendapatkan satu entri dari hashmap tanpa iterasi

172

Apakah ada cara yang elegan untuk mendapatkan hanya satu Entry<K,V>dari HashMap, tanpa iterasi, jika kuncinya tidak diketahui.

Karena urutan entri tidak penting, bisakah kita mengatakan sesuatu seperti

hashMapObject.get(zeroth_index);

Meskipun saya sadar bahwa tidak ada metode indeks get get.

Jika saya mencoba pendekatan yang disebutkan di bawah, itu masih harus mendapatkan semua set entri hashmap .

for(Map.Entry<String, String> entry : MapObj.entrySet()) {
    return entry;
}

Saran diterima.

EDIT: Tolong sarankan Struktur Data lain untuk mencukupi persyaratan.

nilesh
sumber

Jawaban:

93

Jawaban Jesper bagus. Solusi lain adalah dengan menggunakan TreeMap (Anda meminta struktur data lainnya).

TreeMap<String, String> myMap = new TreeMap<String, String>();
String first = myMap.firstEntry().getValue();
String firstOther = myMap.get(myMap.firstKey());

TreeMap memiliki overhead sehingga HashMap lebih cepat, tetapi hanya sebagai contoh solusi alternatif.

Per Östlund
sumber
Atau ConcurrentSkipListMap
Stephen Denne
Untuk beberapa alasan, firstEntry()metode tidak didefinisikan dalam antarmuka SortedMaptetapi hanya dalam TreeMapdan ConcurrentSkipListMap:(
Janko
1
firstEntry () didefinisikan dalam antarmuka NavigableMap.
Per Östlund
Ah, terima kasih, saya hanya melihatnya SortedMapkarena punya firstKey()metode.
janko
251

Peta tidak diurutkan, jadi tidak ada yang namanya 'entri pertama', dan itu juga sebabnya tidak ada metode get-by-index pada Map(atau HashMap).

Anda bisa melakukan ini:

Map<String, String> map = ...;  // wherever you get this from

// Get the first entry that the iterator returns
Map.Entry<String, String> entry = map.entrySet().iterator().next();

(Catatan: Memeriksa peta kosong dihilangkan).

Kode Anda tidak mendapatkan semua entri di peta, ia segera kembali (dan keluar dari loop) dengan entri pertama yang ditemukan.

Untuk mencetak kunci dan nilai elemen pertama ini:

System.out.println("Key: "+entry.getKey()+", Value: "+entry.getValue());

Catatan: Memanggil iterator()tidak berarti Anda mengulangi seluruh peta.

Jesper
sumber
3
Hanya catatan tambahan: LinkedHashMapsimpan kunci sesuai urutan yang dimasukkan.
Matthieu
2
Ya, peta secara umum tidak dipesan, tetapi beberapa Mapimplementasi seperti LinkedHashMapdan TreeMapmemang memiliki urutan yang ditentukan. ( HashMaptidak).
Jesper
1
Jawaban yang lebih baik daripada jawaban yang dipilih - karena jawaban yang dipilih menggunakan TreeMap yang mengharapkan kunci bertipe Sebanding.
Yazad
28

Saya kira iterator mungkin solusi paling sederhana.

return hashMapObject.entrySet().iterator().next();

Solusi lain (tidak cantik):

return new ArrayList(hashMapObject.entrySet()).get(0);

Atau (tidak lebih baik):

return hashMapObject.entrySet().toArray()[0];
cadrian
sumber
7
Tidak ada alasan untuk menggunakan versi kedua atau ketiga. Yang pertama baik-baik saja, dua lainnya menghabiskan banyak waktu dengan menyediakan array / Daftar tanpa biaya.
Joachim Sauer
4
Saya setuju, oleh karena itu komentar "tidak cantik" ;-)
cadrian
14

Dapatkan nilai, konversi ke array, dapatkan elemen pertama array:

map.values().toArray()[0]

W.

Wiktor Misiek
sumber
8

Mengapa Anda ingin menghindari memanggil entrySet()itu tidak umum membuat obyek yang sama sekali baru dengan konteks sendiri, tapi malah memberikan objek fasad. Cukup berbicara entrySet()adalah operasi yang cukup murah.

Joachim Sauer
sumber
8

Jika Anda menggunakan Java 8, sesederhana findFirst () :

Contoh cepat:

Optional<Car> theCarFoundOpt = carMap.values().stream().findFirst();

if(theCarFoundOpt.isPresent()) {
    return theCarFoundOpt.get().startEngine();
}
Cacho Santa
sumber
6

Jika Anda benar-benar menginginkan API yang Anda sarankan, Anda dapat mensubkontrakkan HashMap dan melacak kunci dalam Daftar misalnya. Tidak benar-benar mengerti maksudnya, tetapi ini memberi Anda apa yang Anda inginkan. Jika Anda menjelaskan kasus penggunaan yang dimaksud, mungkin kita dapat menemukan solusi yang lebih baik.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("unchecked")
public class IndexedMap extends HashMap {

    private List<Object> keyIndex;

    public IndexedMap() {
        keyIndex = new ArrayList<Object>();
    }

    /**
     * Returns the key at the specified position in this Map's keyIndex.
     * 
     * @param index
     *            index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException
     *             if the index is out of range (index < 0 || index >= size())
     */
    public Object get(int index) {
        return keyIndex.get(index);
    }

    @Override
    public Object put(Object key, Object value) {

        addKeyToIndex(key);
        return super.put(key, value);
    }

    @Override
    public void putAll(Map source) {

        for (Object key : source.keySet()) {
            addKeyToIndex(key);
        }
        super.putAll(source);
    }

    private void addKeyToIndex(Object key) {

        if (!keyIndex.contains(key)) {
            keyIndex.add(key);
        }
    }

    @Override
    public Object remove(Object key) {

        keyIndex.remove(key);
        return super.remove(key);
    }
}

EDIT: Saya sengaja tidak mempelajari sisi generik dari ini ...

Adriaan Koster
sumber
4

Apa yang Anda maksud dengan "tanpa iterasi"?

Anda dapat menggunakan map.entrySet().iterator().next()dan Anda tidak akan beralih melalui peta (dalam arti "menyentuh setiap objek"). Anda tidak bisa mendapatkan Entry<K, V>tanpa menggunakan iterator. Javadoc of Map.Entry mengatakan:

Metode Map.entrySet mengembalikan tampilan koleksi peta, yang elemennya dari kelas ini. Satu-satunya cara untuk mendapatkan referensi ke entri peta adalah dari iterator tampilan koleksi ini. Peta ini. Objek objek hanya berlaku selama durasi iterasi.

Bisakah Anda menjelaskan lebih detail, apa yang ingin Anda capai? Jika Anda ingin menangani objek terlebih dahulu, yang cocok dengan kriteria tertentu (seperti "memiliki kunci tertentu") dan kembali ke objek yang tersisa, kemudian lihat pada PriorityQueue . Ini akan memesan objek Anda berdasarkan pesanan alami atau yang ditentukan khusus Comparatoryang Anda berikan.

janko
sumber
4
import java.util.*;

public class Friday {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>();

        map.put("code", 10);
        map.put("to", 11);
        map.put("joy", 12);

        if (! map.isEmpty()) {
            Map.Entry<String, Integer> entry = map.entrySet().iterator().next();
            System.out.println(entry);
        }
    }
}

Pendekatan ini tidak berhasil karena Anda menggunakan HashMap. Saya berasumsi menggunakan LinkedHashMap akan menjadi solusi yang tepat dalam kasus ini.

dmgcodevil
sumber
1
Metode apa yang ada di LinkedHashMap yang membuat LinkedHashmap berfungsi, sehingga kode ini tidak?
SL Barth - Reinstate Monica
3

Ini akan mendapatkan satu entri dari peta, yang sedekat mungkin, mengingat 'pertama' tidak benar-benar berlaku.

import java.util.*;

public class Friday {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>();

        map.put("code", 10);
        map.put("to", 11);
        map.put("joy", 12);

        if (! map.isEmpty()) {
            Map.Entry<String, Integer> entry = map.entrySet().iterator().next();
            System.out.println(entry);
        }
    }
}
Michael Easter
sumber
2

Tersandung di sini mencari hal yang sama ... Saya kemudian ingat Iterableskelas dari perpustakaan Jambu .

Untuk mendapatkan "pertama" elemen: Iterables.getFirst( someMap.values(), null );.
Pada dasarnya melakukan hal yang sama Map.values().iterator().next(), tetapi juga memungkinkan Anda untuk menentukan default (dalam hal ini nol) jika tidak ada apa pun di Peta.

Iterables.getLast( someMap.values(), null ); mengembalikan elemen terakhir di Peta.

Iterables.get( someMap.values(), 7, null ); mengembalikan elemen ke-7 di Peta jika ada, jika tidak nilai default (dalam hal ini nol).

Ingat juga bahwa HashMaps tidak dipesan ... jadi jangan berharap Iterables.getFirstuntuk mengembalikan item pertama yang Anda lemparkan ke sana ... juga Iterables.getLast. Mungkin berguna untuk mendapatkan sebuah nilai dipetakan sekalipun.

Mungkin tidak layak menambahkan perpustakaan Guava hanya untuk itu, tetapi jika Anda kebetulan menggunakan beberapa utilitas keren lainnya di dalam perpustakaan itu ...

SquidRott
sumber
1

Mengikuti EDIT Anda, inilah saran saya:

Jika Anda hanya memiliki satu entri, Anda dapat mengganti Peta dengan objek ganda. Tergantung pada jenisnya, dan preferensi Anda:

  • sebuah array (dari 2 nilai, kunci dan nilai)
  • objek sederhana dengan dua properti
KLE
sumber
0
map<string,string>m;
auto it=m.begin();//get iterator to the first element of map(m)
return m->first;//return first string(1st string in map<string,string>m)
//Incase you want the second string 
//you can use return m->second(2st string in map<string,string>m)
//if you want to iterate the whole map you can use loop
for(auto it:m)//m is a map
   cout<<it->first<<endl;
Vipul Vikram
sumber
4
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
Alex Riabov
1
Ya, silakan tambahkan beberapa penjelasan bersama dengan kode Anda.
jkdev
-3

Saya mendapat jawabannya: (Sederhana saja)

Ambil ArrayList, lalu masukkan dan temukan ukuran daftar array. Ini dia :

    ArrayList count = new ArrayList();
    count=(ArrayList) maptabcolname.get("k1"); //here "k1" is Key
    System.out.println("number of elements="+count.size());

Ini akan menunjukkan ukurannya. (Berikan saran). Bekerja.

Indranil Banerjee
sumber
2
Bagaimana cara mendapatkan satu item sembarang dari peta hash?
Kolonel Thirty Two