반복하지 않고 해시 맵에서 하나의 항목을 얻는 방법


172

Entry<K,V>키를 알 수없는 경우 반복하지 않고 HashMap에서 하나만 얻는 우아한 방법이 있습니까?

입국 순서는 중요하지 않으므로 다음과 같이 말할 수 있습니다.

hashMapObject.get(zeroth_index);

인덱스 방법에 의한 get이 없다는 것을 알고 있지만.

아래에 언급 된 접근 방식을 시도해도 여전히 hashmap의 모든 항목 세트를 가져와야 합니다.

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

제안은 환영합니다.

편집 : 요구 사항을 충족시키기 위해 다른 데이터 구조를 제안하십시오.

답변:


93

Jesper의 답변이 좋습니다. 다른 솔루션은 TreeMap을 사용하는 것입니다 (다른 데이터 구조를 요청한 경우).

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

TreeMap에는 오버 헤드가 있으므로 HashMap이 더 빠르지 만 대안 솔루션의 예와 같습니다.


또는 ConcurrentSkipListMap
Stephen Denne

어떤 이유로, firstEntry()메소드는 인터페이스에 정의되어 있지 않고 and and SortedMap에만 있습니다. (TreeMapConcurrentSkipListMap
janko

1
firstEntry ()는 NavigableMap 인터페이스에 정의되어 있습니다.
Per Östlund

아, 고마워요 . 방법 SortedMap이 있었기 때문에 보았습니다 firstKey().
janko

251

지도는 순서가 정해져 있지 않으므로 '첫 번째 항목'과 같은 항목이 없으므로 Map(또는 HashMap) 에 색인으로 가져 오기 방법이없는 이유도 있습니다 .

당신은 이것을 할 수 있습니다 :

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

(참고 : 빈지도 확인 생략).

코드는 맵의 모든 항목을 가져 오지 않으며 발견 된 첫 번째 항목과 함께 즉시 리턴 (루프에서 나옴)합니다.

이 첫 번째 요소의 키와 값을 인쇄하려면

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

참고 : 전화 iterator()한다고해서 전체지도를 반복한다는 의미는 아닙니다.


3
참고 사항 : LinkedHashMap키를 삽입 된 순서대로 유지하십시오.
Matthieu

2
네, 일반적으로 주문한되지 않습니다에 매핑하지만, 일부 Map등의 구현 LinkedHashMap과는 TreeMap정의 된 순서를해야합니까. ( HashMap하지 않습니다).
Jesper

1
선택한 답변이 TreeMap을 사용하므로 키가 Comparable 유형이 될 것으로 예상되므로 선택한 답변보다 나은 답변입니다.
Yazad

28

반복자가 가장 간단한 해결책 일 수 있습니다.

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

또 다른 해결책 (예쁘지 않음) :

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

또는 아직 (더 좋지 않음) :

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

7
두 번째 또는 세 번째 버전을 사용할 이유가 없습니다. 첫 번째는 완벽하게 괜찮고 다른 두 가지는 아무것도없는 배열 / 목록을 제공하여 많은 시간을 낭비합니다.
Joachim Sauer

4
동의합니다. 따라서 "예쁘지 않은"의견 ;-)
cadrian

14

값을 가져 와서 배열로 변환하고 배열의 첫 번째 요소를 가져옵니다.

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

W.


8

왜 전화하지 않으려 할 entrySet()않습니다 그것을 하지 일반적으로 자신의 상황과 완전히 새로운 개체를 만들 수 있지만 대신 외관 객체를 제공합니다. 간단히 말해서 entrySet()꽤 저렴한 작업입니다.


8

Java 8을 사용하는 경우 findFirst () 만큼 간단합니다 .

빠른 예 :

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

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

6

제안한 API를 정말로 원한다면 HashMap을 서브 클래 싱하고 목록에서 키를 추적 할 수 있습니다. 이 점을 실제로 보지는 않지만 원하는 것을 제공합니다. 의도 된 사용 사례를 설명하면 더 나은 솔루션을 얻을 수 있습니다.

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

편집 : 나는 의도적으로 이것의 제네릭 측면을 탐구하지 않았습니다 ...


4

"반복하지 않고"는 무슨 뜻입니까?

사용할 수 있고 map.entrySet().iterator().next()맵을 반복하지 않습니다 ( "각 오브젝트 터치"의 의미로). Entry<K, V>반복자를 사용하지 않고 는 붙잡을 수 없습니다 . Map.Entry 의 Javadoc은 다음과 같이 말합니다.

Map.entrySet 메소드는 요소가이 클래스에 속하는 맵의 콜렉션 뷰를 리턴합니다. 지도 항목에 대한 참조를 얻는 유일한 방법은이 컬렉션 뷰의 반복자입니다. 이러한 Map.Entry 객체는 반복 기간 동안 만 유효합니다.

달성하려는 내용을 더 자세히 설명 할 수 있습니까? 먼저 "특정 키를 가짐"과 같은 특정 기준과 일치하는 오브젝트를 처리하려면 나머지 오브젝트로 폴백하고 PriorityQueue를보십시오 . 자연 순서 또는 사용자가 Comparator제공 한 사용자 정의에 따라 객체를 주문 합니다.


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을 사용했기 때문에이 방법이 작동하지 않습니다. 이 경우 LinkedHashMap을 사용하는 것이 올바른 해결책이라고 가정합니다.


1
LinkedHashMap 에서 LinkedHashmap 을 작동시키는 방법은 무엇입니까 ?
SL Barth-복원 모니카

3

이것은 '첫 번째'가 실제로 적용되지 않는 한 맵에서 하나의 항목을 얻을 수 있습니다.

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

같은 것을 찾아 여기에서 우연히 발견 ... 구아바 도서관Iterables 에서 수업 을 기억했다 .

"first"요소를 얻으려면 : Iterables.getFirst( someMap.values(), null );.
기본적으로와 동일 Map.values().iterator().next()하지만 맵에 아무것도없는 경우 기본값 (이 경우 null)을 지정할 수 있습니다.

Iterables.getLast( someMap.values(), null ); 지도의 마지막 요소를 반환합니다.

Iterables.get( someMap.values(), 7, null ); 존재하는 경우 Map에서 7 번째 요소를 반환하고, 그렇지 않으면 기본값 (이 경우 null)을 반환합니다.

HashMaps는 주문되지 않았 음을 기억하십시오. 따라서 Iterables.getFirst처음으로 던진 항목을 반환 하지 않아도 됩니다 Iterables.getLast. 그래도 매핑 된 값 을 얻는 것이 유용 할 것 입니다.

Guava 라이브러리를 추가하는 것은 가치가 없지만 해당 라이브러리 내에서 다른 멋진 유틸리티를 사용하는 경우 ...


1

편집 후 다음은 내 제안입니다.

항목이 하나만 있으면 맵을 이중 객체로 바꿀 수 있습니다. 유형 및 환경 설정에 따라

  • 배열 (2 개의 값, 키 및 값)
  • 두 가지 속성을 가진 간단한 객체

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
이 코드는 질문에 대답 할 수 있지만,이 코드가 질문에 응답하는 이유 및 / 또는 방법에 대한 추가 컨텍스트를 제공하면 장기적인 가치가 향상됩니다.
Alex Riabov

1
예, 코드와 함께 설명을 추가하십시오.
jkdev

-3

나는 대답을 얻었다 : (단순하다)

ArrayList를 가져 와서 캐스트하고 arraylist의 크기를 찾으십시오. 여기있어 :

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

크기가 표시됩니다. (제안하기). 작동합니다.


2
이것은 해시 맵에서 임의의 항목을 어떻게 얻습니까?
대령 삼십이
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.