tekrarlamadan hashmap'tan bir giriş nasıl alınır


172

Entry<K,V>Eğer anahtar bilinmiyorsa, yinelemeden HashMap'ten sadece bir tane almanın zarif bir yolu var mı ?

Giriş sırası önemli olmadığından,

hashMapObject.get(zeroth_index);

Her ne kadar böyle bir get index yöntemi ile var olduğunun farkında olmasına rağmen.

Aşağıda belirtilen yaklaşımı deneseydim, hala hashmap'in tüm giriş setini almak zorunda kalacaktı .

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

Öneriler bekliyoruz.

EDIT: gereksinimi karşılamak için başka herhangi bir Veri Yapısı öneririz.

Yanıtlar:


93

Jesper'in cevabı iyi. Diğer bir çözüm ise TreeMap kullanmaktır (diğer veri yapılarını istediniz).

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

TreeMap'in ek yükü vardır, bu nedenle HashMap daha hızlıdır, ancak alternatif bir çözüm örneği olarak.


Veya ConcurrentSkipListMap
Stephen Denne

Herhangi bir nedenle, firstEntry()yöntem arabirimde SortedMapdeğil, yalnızca TreeMapve ConcurrentSkipListMap: tanımlı :(
janko

1
firstEntry (), NavigableMap arayüzünde tanımlanır.
Per Östlund

Ah, teşekkürler, sadece baktım SortedMapçünkü firstKey()metodu vardı .
janko

251

Haritalar sipariş edilmemiştir, bu nedenle 'ilk giriş' diye bir şey yoktur ve bu nedenle Map(veya HashMap) üzerinde endeksle alma yöntemi yoktur .

Bunu yapabilirsin:

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();

(Not: Boş bir haritanın kontrol edilmemesi).

Kodunuz haritadaki tüm girişleri almaz, bulunan ilk girişle birlikte hemen döner (ve döngüden çıkar).

Bu ilk öğenin anahtarını ve değerini yazdırmak için:

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

Not: Arama yapmak iterator(), haritanın tamamında yineleme yaptığınız anlamına gelmez.


3
Sadece bir yan not: LinkedHashMapanahtarları yerleştirildikleri sırayla tutar.
Matthieu

2
Evet, genel olarak haritalar sipariş edilmez, ancak ve Mapgibi bazı uygulamaların tanımlanmış bir sırası vardır. ( değil). LinkedHashMapTreeMapHashMap
Jesper

1
Seçilen cevaptan daha iyi cevap - seçilen cevap anahtarın Karşılaştırılabilir tipte olmasını bekleyen TreeMap kullandığından.
Yazad

28

Yineleyici en basit çözüm olabilir sanırım.

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

Başka bir çözüm (hoş değil):

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

Veya henüz (daha iyi değil):

return hashMapObject.entrySet().toArray()[0];

7
İkinci veya üçüncü sürümü kullanmak için hiçbir neden yoktur. Birincisi gayet iyi, diğer ikisi ise hiçbir şey için bir dizi / Liste sağlayarak çok zaman kaybediyor.
Joachim Sauer

4
Kabul ediyorum, bu nedenle "hoş değil" yorumlar ;-)
cadrian

14

Değerleri alın, bir diziye dönüştürün, dizinin ilk öğesini alın:

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

W.


8

Neden arama önlemek istiyorsun entrySet()o kötü değil genel olarak kendi bağlamı ile tamamen yeni bir nesne oluşturmak, ancak bunun yerine sadece bir cephe nesne sağlar. Basitçe söylemek gerekirse entrySet()oldukça ucuz bir işlem.


8

Java 8 kullanıyorsanız, findFirst () kadar basittir :

Hızlı örnek:

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

if(theCarFoundOpt.isPresent()) {
    return theCarFoundOpt.get().startEngine();
}

6

Önerdiğiniz API'yı gerçekten istiyorsanız HashMap'i alt sınıflandırabilir ve örneğin bir Listedeki anahtarları takip edebilirsiniz. Buradaki noktayı gerçekten görmüyorum, ama size ne istediğinizi veriyor. Kullanım amacını açıklarsanız, belki daha iyi bir çözüm bulabiliriz.

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);
    }
}

DÜZENLEME: Kasten bunun jenerikler tarafına girmedim ...


4

"Tekrarlamadan" ile ne demek istiyorsun?

map.entrySet().iterator().next()Harita üzerinde kullanabilirsiniz ve "her nesneye dokunmak" anlamında yineleme yapamazsınız. Entry<K, V>Yine de bir yineleyici kullanmadan tutamazsınız . Map of Javadoc.Entry diyor ki:

Map.entrySet yöntemi, öğeleri bu sınıfta olan haritanın bir koleksiyon görünümünü döndürür. Bir harita girişine referans almanın tek yolu, bu toplama görünümünün yineleyicisidir. Bu Map.Entry nesneleri yalnızca yineleme süresince geçerlidir.

Neyi başarmaya çalıştığınızı daha ayrıntılı olarak açıklayabilir misiniz? Önce nesneleri işlemek istiyorsanız, belirli bir ölçütle eşleşen ("belirli bir anahtarınız var" gibi) ve geri kalan nesnelere geri dönün, sonra bir PriorityQueue'ya bakın . Nesnelerinizi doğal düzene veya Comparatorsağladığınız özel tanımlı bir şekilde sıralar .


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);
        }
    }
}

HashMap kullandığınız için bu yaklaşım işe yaramıyor. LinkedHashMap kullanarak bu durumda doğru çözüm olacağını varsayalım.


1
LinkedHashMap içinde LinkedHashmap'ı çalıştıran , bu kodun çalışmadığı hangi yöntem var ?
SL Barth - Monica'yı eski haline getirin

3

Bu, haritadan tek bir giriş alacaktır; bu, 'ilk' verildiğinde gerçekte geçerli olmadığı kadar yakın olabilir.

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);
        }
    }
}

2

Burada aynı şeyi arayan tökezledi ... Daha sonra Guava kütüphanesindenIterables dersi hatırladım .

"İlk" elemanı almak için: Iterables.getFirst( someMap.values(), null );.
Aslında aynıMap.values().iterator().next() , ancak aynı zamanda Harita'da hiçbir şey olmaması durumunda bir varsayılan (bu durumda null) belirtmenize izin verir.

Iterables.getLast( someMap.values(), null ); Haritadaki son öğeyi döndürür.

Iterables.get( someMap.values(), 7, null ); Haritadaki 7. öğeyi döndürür, aksi takdirde varsayılan bir değer (bu durumda null) döndürür.

HashMaps'in sipariş edilmediğini unutmayın ... bu yüzden Iterables.getFirstorada attığınız ilk öğeyi iade etmeyi beklemeyin ... aynı şekilde Iterables.getLast. Almak Belki kullanışlı bir olsa eşleştirilmiş değeri.

Bunun için Guava kütüphanesini eklemeye değmeyebilir, ancak bu kütüphanedeki diğer harika yardımcı programları kullanıyorsanız ...


1

EDIT'inizin ardından, işte önerim:

Yalnızca bir girişiniz varsa, Harita'yı ikili bir nesne ile değiştirebilirsiniz. Türlerine ve tercihlerinize bağlı olarak:

  • bir dizi (2 değer, anahtar ve değer)
  • iki özelliği olan basit bir nesne

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;

4
Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini artırır.
Alex Riabov

1
Evet, lütfen kodunuzla birlikte bir açıklama ekleyin.
jkdev

-3

Cevabı aldım: (Çok basit)

Bir ArrayList alın ve yayınlayın ve arraylistin boyutunu bulun. İşte burada :

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

Boyutu gösterecektir. (Öneri verin). İşe yarıyor.


2
Bu karma haritadan bir keyfi öğeyi nasıl alır?
Albay Otuz İki
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.