Java Sıralı Haritası


322

Java'da, anahtar / değer çiftlerini saklamak ve bunlara erişmek için Harita gibi davranan, ancak anahtar ve değer listelerinin aynı sırada olması için sıralı bir anahtar listesi ve sıralı bir değer listesi döndürebilen bir nesne var mı?

Kod tarafından açıklama olarak, hayali OrderedMap gibi davranan bir şey arıyorum:

OrderedMap<Integer, String> om = new OrderedMap<>();
om.put(0, "Zero");
om.put(7, "Seven");

String o = om.get(7); // o is "Seven"
List<Integer> keys = om.getKeys();
List<String> values = om.getValues();

for(int i = 0; i < keys.size(); i++)
{
    Integer key = keys.get(i);
    String value = values.get(i);
    Assert(om.get(key) == value);
}

4
Yapmak istediğiniz tek şey her ikisini de aynı anda tekrarlamaksa, Map.entrySet () bunu herhangi bir haritada yapmanıza izin verecektir. LinkedHashMap iyi tanımlanmış bir sıraya sahiptir, ancak herhangi bir Harita için giriş kümesi anahtar / değer çiftlerini yansıtır.
Pete Kirkham

5
Herhangi bir Harita uygulaması örnek kodunuz gibi davranacağından, bu kod iyi bir örnek değildir. sıralanır, sıralanır veya sıralanmaz.
Peter Lawrey

2
Sun JDK uygulamasında, getKeys ve getValues ​​() kümeleri tarafından döndürülen kümeler haritadaki inputSet () tarafından desteklenir, dolayısıyla örnek testlerinizin aynı yineleme sırasına sahip olacaktır.
Pete Kirkham

4
Bu ilginç, bunu hiç fark etmedim. Yine de, beni çılgın olarak adlandırın, ancak arabirim tarafından açıkça doğrulanmayan uygulama hakkında varsayımlar yapmamayı tercih ediyorum. Geçmişte bunu defalarca yaktım.
09:00

2
Sıralı Harita farklı bir şey olduğu için buna Java Sıralı Harita adı verilmelidir - bkz LinkedHashMap.
Ondra 16ižka

Yanıtlar:


397

SortedMap (uygulamasıyla arayüz TreeMap ) arkadaşınız olmalıdır.

Arayüzün yöntemleri vardır:

  • keySet() bir dizi tuşu artan sırada döndürür
  • values() karşılık gelen tuşların artan sırasına göre tüm değerlerin bir koleksiyonunu döndüren

Böylece bu arayüz gereksinimlerinizi tam olarak karşılar. Ancak, anahtarların anlamlı bir sıraya sahip olması gerekir. Aksi takdirde , siparişin ekleme siparişine göre belirlendiği LinkedHashMap öğesini kullanabilirsiniz .


2
örnek: SortedMap <String, Object> map = yeni TreeMap <> ();
Ben

7
TreeMap kullanmak için, anahtar sınıfın Karşılaştırılabilir arabirim uygulaması gerekir. Değilse, bir tür RuntimeException oluşturulur. TreeMap aynı zamanda harita sıralanmış, ama yazar sadece sipariş (sıralanmamış) harita kullanmak istiyorum düşünüyorum. LinkedHashMap yalnızca sipariş edilen haritayı almak için iyi bir seçimdir (dediğiniz gibi, "ekleme siparişi ile belirlenir").
K. Gol

1
Bu cevap

4
Gönderen java 8 doc . LinkedHashMapyineleme sırası girişlerine en son erişildiği sıra olan
TRiNE

1
@TRiNE Yorumunuzu takip etmiyorum, ancak bir bağlamı kaçırmış olabilirim. Varsayılan olarak LinkedHashMapyineleme sırası ekleme siparişidir, ancak bunun yerine erişim sırasını belirtmek için farklı bir kurucu kullanabilirsiniz. docs.oracle.com/javase/8/docs/api/java/util/…
rob

212

Anahtar / değer çiftlerini saklamak ve bunlara erişmek için Harita gibi davranan ancak anahtar ve değer listeleri aynı sırada olacak şekilde sıralı bir anahtar listesi ve sıralı bir değer listesi döndürebilen bir nesne var mı?

Java.util.LinkedHashMap'i arıyorsunuz . Her zaman aynı sırada yinelenen Map.Entry <K, V> çiftlerinin bir listesini alırsınız. Bu sipariş, öğeleri koyduğunuz sıra ile aynıdır. Alternatif olarak, anahtarların ya doğal bir sıraya sahip olması ya da a ile belirtilmesi gereken java.util.SortedMap öğesini kullanın .Comparator


14
Ve sadece bunu kontrol ederek okuyucuyu tekrar kontrol etmek için, test ederek doğrulamak zor olduğundan, keySet()yöntem etkili bir şekilde, put()aramalarınızın sırasını yansıtan bir LinkedHashSet döndürür . put()Aynı tuş için yapılan tekrarlanan çağrıların, siz remove()önceden anahtar olmadıkça sırayı değiştirmeyeceğini unutmayın .
Glenn Lawrence

Gönderen java 8 doc . LinkedHashMapyineleme sırası girişlerine en son erişildiği sıra olan
TRiNE

24

LinkedHashMap anahtarların sırasını korur.

java.util.LinkedHashMap normal bir HashMap gibi çalışıyor gibi görünüyor.


1
Bu soruya bir cevap sağlamaz. Bir yazardan eleştiri veya açıklama istemek için gönderilerinin altına bir yorum bırakın - her zaman kendi yayınlarınıza yorum yapabilirsiniz ve yeterli bir üne sahip olduğunuzda herhangi bir yazı hakkında yorum yapabilirsiniz .
ianaya89

2
@ ianaya89 Bunun gerçek bir cevap olduğunu düşünüyorum, ancak John Feminella'nın cevabına çok benziyor !
T30

1
Girişlerin haritaya koyduğunuz sırada bu sırada saklandığı sıralı bir harita almak istiyorsanız, LinkedHapMap doğru cevaptır. Haritanızdaki girişleri, girdiğiniz sıradan bağımsız olarak sıralamak istiyorsanız, bir SortedMap doğru cevaptır.
Ralph

@TRiNE Bağladığınız java 8 dokümanı iki sipariş modu olduğunu söylüyor: ekleme talimatı ve erişim sırası. Özel bir kurucu ortak LinkedHashMap (int initialCapacity, float loadFactor, boolean accessOrder) kullanılarak çağrılan ikincisi hakkında düşünürsünüz. Varsayılan yapıcı, ekleme emri verilen LinkedHashMap örneği oluşturur.
Artur Łysik

1
@ ArturŁysik evet öyle. Günler önce yaptığım bir hataydı. Ben düzeltirim. Yorumu siliyorum. artık düzenleyemediğim için
TRiNE

7

Sanırım çerçeveden alacağınız en yakın koleksiyon SortedMap


3
Eğer puan kaybetmeye değer olduğunu düşünseydim bu cevabı aşağıya indirirdim. Yukarıdaki cevabın işaret ettiği gibi, cevabınızda LinkedHashMap hakkında doğru bilgiler bulunmuyor ve SortedMap'in küçük bir açıklaması da iyi olurdu.
CorayThan

@CorayThan, bu durumda en iyi cevapları onaylarsınız, doğru olabilecek ancak en iyisi olmayanları aşağıya değil ...
bruno conde

1
Ben de öyle yaptım. Sadece birinin neden oy verdiğini anlayabildiğimi söyleyerek.
CorayThan

5

Artan veya azalan tuş sırasıyla erişilebilen ve geçilebilen NavigableMap arayüzünden yararlanabilirsiniz . Bu arayüzün yerini almak SortedMap arayüzünün üzere . Gezilebilir harita genellikle tuşlarının doğal sıralamasına veya harita oluşturma sırasında sağlanan bir Karşılaştırıcıya göre sıralanır.

En yararlı üç uygulaması vardır: TreeMap , ImmutableSortedMap ve ConcurrentSkipListMap .

TreeMap örneği:

TreeMap<String, Integer> users = new TreeMap<String, Integer>();
users.put("Bob", 1);
users.put("Alice", 2);
users.put("John", 3);

for (String key: users.keySet()) {
  System.out.println(key + " (ID = "+ users.get(key) + ")");
}

Çıktı:

Alice (ID = 2)
Bob (ID = 1)
John (ID = 3)



2

tl; Dr.

Map< Integer , String >Tuşa göre sıralanmış bir sırayla tutmak için , SortedMap/ NavigableMaparabirimlerini uygulayan iki sınıftan birini kullanın :

  • TreeMap
  • ConcurrentSkipListMap

Haritayı tek bir iş parçacığında değiştiriyorsanız, ilk TreeMap,. Eğer dişler arasında manipüle ediyorsanız, ikincisini kullanın ConcurrentSkipListMap.

Ayrıntılar için aşağıdaki tabloya ve aşağıdaki tartışmaya bakın.

ayrıntılar

MapJava 11 ile birlikte verilen on uygulamanın özelliklerini gösteren bir grafik tablo .

NavigableMapArayüz nedir SortedMapilk etapta olmalıydı. SortedMapMantıksal kaldırılması gerektiğini ancak bazı 3. taraf haritası uygulamaları arayüzü kullanarak edilebilir olamaz.

Bu tabloda görebileceğiniz gibi, SortedMap/ NavigableMaparabirimlerini yalnızca iki sınıf uygular :

Sıralanmış sırayla bu tutmak tuşlarından Hem, ya onların doğal emriyle (kullanarak compareToyöntemi Comparable( https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ Comparable.html ) arayüzü) veya geçirdiğiniz bir Comparatoruygulama ile. Bu iki sınıf arasındaki fark, ikinci bir, yani ConcurrentSkipListMap, bir evreli yüksek eşzamanlı .

Aşağıdaki tabloda yer alan Yineleme sırası sütununa da bakın.

  • LinkedHashMapSınıf onlar sırayla onun girişleri döndürür aslen yerleştirilen .
  • EnumMapgirişleri anahtarın enum sınıfının tanımlandığı sıraya göre döndürür . Örneğin, hangi çalışanın haftanın hangi gününü kapsadığını gösteren bir harita ( Map< DayOfWeek , Person >) DayOfWeekJava'da yerleşik enum sınıfını kullanır . Bu numaralandırma ilk Pazartesi ve son Pazar ile tanımlanır. Yani bir yineleyicideki girdiler bu sırayla görünecektir.

Diğer altı uygulama, girdilerini bildirdikleri sıra hakkında hiçbir söz vermemektedir.

Java 11'deki harita uygulamalarının özelliklerini karşılaştırma tablosu


0

Bir haritayı değerlere göre sıralamak için Basit Karma harita, bağlantılı liste ve Koleksiyonlar kullandım.

import java.util.*;
import java.util.Map.*;
public class Solution {

    public static void main(String[] args) {
        // create a simple hash map and insert some key-value pairs into it
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("Python", 3);
        map.put("C", 0);
        map.put("JavaScript", 4);
        map.put("C++", 1);
        map.put("Golang", 5);
        map.put("Java", 2);
        // Create a linked list from the above map entries
        List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
        // sort the linked list using Collections.sort()
        Collections.sort(list, new Comparator<Entry<String, Integer>>(){
        @Override
         public int compare(Entry<String, Integer> m1, Entry<String, Integer> m2) {
        return m1.getValue().compareTo(m2.getValue());
        }
      });
      for(Entry<String, Integer> value: list) {
         System.out.println(value);
     }
   }
}

Çıktı:

C=0
C++=1
Java=2
Python=3
JavaScript=4
Golang=5
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.