자바 주문지도


322

Java에는 키 / 값 쌍을 저장하고 액세스하기위한 맵처럼 작동하지만 키 및 값 목록이 동일한 순서로 정렬 된 키 목록과 정렬 된 값 목록을 리턴 할 수있는 오브젝트가 있습니까?

코드 별 설명으로 가상의 OrderedMap처럼 동작하는 것을 찾고 있습니다.

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
원하는 모든 것이 동시에 두 가지를 반복하는 경우 Map.entrySet ()을 사용하면 모든지도 에서이 작업을 수행 할 수 있습니다. LinkedHashMap은 잘 정의 된 순서를 갖지만 모든 Map에 대해 항목 세트는 키 / 값 쌍을 반영합니다.
피트 Kirkham

5
모든 Map 구현이 샘플 코드로 작동하므로이 코드는 좋은 예가 아닙니다. 정렬, 정렬 또는 미정.
피터 로리

2
Sun JDK 구현에서 getKeys 및 getValues ​​() 세트가 리턴 한 세트는 맵의 entrySet ()에 의해 지원되므로 동일한 반복 순서를 가지게됩니다. 이는 샘플이 테스트하는 것입니다.
Pete Kirkham

4
글쎄요, 흥미 롭습니다. 그래도 미쳤다고 생각하지만 인터페이스에서 명시 적으로 확인하지 않은 구현에 대한 가정을 선호하지 않습니다. 나는 과거에 그렇게 여러 번 불타고있었습니다.
Whatsit

2
Ordered Map은 다른 점이 있으므로 Java Sorted Map으로 이름을 지정해야합니다 LinkedHashMap.
Ondra Žižka

답변:


397

의 SortedMap의 (구현과 인터페이스 트리 맵은 ) 당신의 친구가되어야한다.

인터페이스에는 다음과 같은 방법이 있습니다.

  • keySet() 키 세트를 오름차순으로 반환
  • values() 이는 해당 키의 오름차순으로 모든 값의 콜렉션을 리턴합니다.

따라서이 인터페이스는 요구 사항을 정확하게 충족시킵니다. 그러나 키에는 의미있는 순서가 있어야합니다. 그렇지 않으면 주문이 게재 신청서에 의해 결정되는 LinkedHashMap을 사용할 수 있습니다 .


2
예 : SortedMap <String, Object> map = new TreeMap <> ();
Ben

7
TreeMap을 사용하려면 키 클래스가 Comparable 인터페이스를 구현해야했습니다. 그렇지 않으면 어떤 종류의 RuntimeException이 발생합니다. TreeMap 그것은 또한 정렬 된지도이지만 저자는 정렬 된 것이 아닌 정렬 된지도를 사용하고 싶다고 생각합니다. LinkedHashMap 순서가 지정된지도 만 얻는 것이 좋습니다 ( "삽입 순서로 결정됨").
K. Gol

1
이 답변은 keySet ()를 반복하는 방법을 보여줌으로써 개선 될 수 있습니다.

4
에서 자바 8 문서 . LinkedHashMap반복 순서는 항목에 마지막으로 액세스
TRiNE

1
@TRiNE 귀하의 의견을 따르지 않지만 일부 내용이 누락되었을 수 있습니다. 기본적으로 LinkedHashMap반복 순서는 삽입 순서이지만 다른 생성자를 사용하여 대신 액세스 순서를 지정할 수 있습니다. docs.oracle.com/javase/8/docs/api/java/util/…
rob

212

키 / 값 쌍을 저장하고 액세스하는 맵처럼 작동하지만 정렬 된 키 목록과 정렬 된 값 목록을 반환하여 키와 값 목록의 순서가 같은 객체가 있습니까?

당신은 java.util.LinkedHashMap을 찾고 있습니다. 항상 같은 순서로 반복되는 Map.Entry <K, V> 쌍 목록이 표시 됩니다. 순서는 항목을 넣는 순서와 동일합니다. 또는 java.util.SortedMap을 사용하십시오. 여기서 키는 자연 순서를 갖거나로 지정해야합니다 Comparator.


14
그리고 테스트를 통해 확인하기가 어렵 기 때문에 독자가 이것을 다시 확인하기 위해이 keySet()메소드는 put()호출 순서를 반영하는 LinkedHashSet을 효과적으로 반환 합니다. put()동일한 키 를 반복해서 호출하면 remove()미리 키를 입력 하지 않는 한 순서가 변경되지 않습니다 .
Glenn Lawrence

에서 자바 8 문서 . LinkedHashMap반복의 그 순서는이다 의 항목이 마지막으로 액세스 된 질서
트린

24

LinkedHashMap은 키의 순서를 유지합니다.

java.util.LinkedHashMap은 일반 HashMap과 동일하게 작동하는 것으로 보입니다.


1
이것은 질문에 대한 답변을 제공하지 않습니다. 작성자의 의견을 비판하거나 설명을 요청하려면 게시물 아래에 댓글을 남겨주세요. 언제든지 자신의 게시물 에 댓글 수 있으며 평판 이 충분 하면 게시물댓글 수 있습니다 .
ianaya89

2
@ ianaya89 이것이 실제 답변이라고 생각하지만 John Feminella의 답변 과 매우 유사합니다 !
T30

1
항목을 맵에 넣을 때 순서대로 저장된 순서 맵을 얻으려면 LinkedHashMap이 정답입니다. 지도 독립적 인 형식으로 항목을 입력 한 순서대로 정렬하려면 SortedMap이 정답입니다.
Ralph

@TRiNE 링크 된 자바 8 문서는 삽입 순서와 액세스 순서의 두 가지 순서 모드가 가능하다고 말합니다. 특별한 생성자 public LinkedHashMap (int initialCapacity, float loadFactor, boolean accessOrder)을 사용하여 호출되는 후자를 생각할 수 있습니다. 기본 생성자는 삽입 순서가 지정된 LinkedHashMap 인스턴스를 만듭니다.
Artur Łysik

1
@ ArturŁysik 그렇습니다. 그것은 며칠 전에 저에 의해 실수였습니다. 수정하겠습니다. 댓글을 삭제하고 있습니다. 더 이상 편집 할 수 없으므로
TRiNE

7

프레임 워크에서 얻을 수있는 가장 가까운 컬렉션은 SortedMap 이라고 생각합니다.


3
나는 그것이 점수를 잃을 가치가 있다고 생각한다면이 답변에 투표를 할 것입니다. 위의 답변에서 알 수 있듯이 귀하의 답변에는 LinkedHashMap에 대한 적절한 정보가 없으며 SortedMap에 대한 약간의 설명도 좋습니다.
CorayThan

@CorayThan,이 경우에 당신은 최고의 답변을 찬성하고, 정확하지만 최고는 아닌 다른 사람들을 공감하지 않습니다 ...
bruno conde

1
그것이 내가 한 일입니다. 왜 누군가가 투표를 거절했는지 이해할 수 있습니다.
CorayThan

5

오름차순 또는 내림차순으로 액세스하고 탐색 할 수있는 NavigableMap 인터페이스를 활용할 수 있습니다 . 이 인터페이스는 SortedMap 인터페이스 를 대체하기위한 것 입니다. 탐색 가능한지도는 일반적으로 키의 자연 순서에 따라 또는지도를 만들 때 제공되는 비교기로 정렬됩니다.

가장 유용한 3 가지 구현이 있습니다 : TreeMap , ImmutableSortedMapConcurrentSkipListMap 입니다.

TreeMap 예 :

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

산출:

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



2

tl; dr

Map< Integer , String >키를 기준으로 정렬 된 순서 를 유지하려면 SortedMap/ NavigableMap인터페이스를 구현하는 두 클래스 중 하나를 사용하십시오 .

  • TreeMap
  • ConcurrentSkipListMap

단일 스레드 내에서 맵을 조작하는 경우 첫 번째을 사용하십시오 TreeMap. 스레드를 조작하는 경우 두 번째를 사용하십시오 ConcurrentSkipListMap.

자세한 내용은 아래 표와 다음 설명을 참조하십시오.

세부

다음은 MapJava 11과 함께 제공되는 10 가지 구현 의 기능을 보여주는 그래픽 표 입니다.

NavigableMap인터페이스는 무엇 SortedMap처음부터 있었어야. SortedMap논리적으로 제거해야하지만 일부 타사지도 구현이 인터페이스를 사용 할 수 있으므로이 될 수 없습니다.

이 표에서 볼 수 있듯이 두 개의 클래스 만 SortedMap/ NavigableMap인터페이스를 구현합니다 .

이 둘은 자연 순서에 따라 키를 정렬 된 순서로 유지 compareTo합니다 Comparable( https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ Comparable.html ) 인터페이스) 또는 Comparator구현에 의해 전달됩니다. 이 두 클래스의 차이점은 두 번째 클래스 ConcurrentSkipListMap스레드로부터 안전 하고 매우 동시 적이라는 것 입니다.

아래 표의 반복 순서 열도 참조하십시오 .

  • LinkedHashMap클래스가 순서대로하여 항목을 반환 원래 삽입 .
  • EnumMap열거 클래스가 정의 된 순서대로 엔트리를 돌려줍니다 . 예를 들어 어떤 직원이 어떤 요일 ( Map< DayOfWeek , Person >)을 다루는 지에 대한 맵은 DayOfWeekJava에 내장 된 enum 클래스를 사용합니다 . 해당 열거 형은 월요일과 일요일이 마지막으로 정의됩니다. 따라서 반복자의 항목은 순서대로 나타납니다.

다른 6 가지 구현은 그들이 출품작을보고하는 순서에 대해 약속하지 않습니다.

기능을 비교 한 Java 11의 맵 구현 표


0

내가 사용한 간단한 해시지도, 링크 된 목록 및 콜렉션의 값을 기준으로지도를 정렬 할 수 있습니다.

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

출력은 다음과 같습니다.

C=0
C++=1
Java=2
Python=3
JavaScript=4
Golang=5
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.