как получить одну запись из hashmap без итерации - PullRequest
156 голосов
/ 02 октября 2009

Существует ли элегантный способ получения только одного Entry<K,V> из HashMap без итерации, если ключ не известен.

Так как порядок ввода записи не важен, можем ли мы сказать что-то вроде

hashMapObject.get(zeroth_index);

Хотя я знаю, что такого метода get by index не существует.

Если бы я попробовал подход, упомянутый ниже, ему все равно пришлось бы получить весь набор записей хэш-карты .

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

Предложения приветствуются.

РЕДАКТИРОВАТЬ: Пожалуйста, предложите любую другую структуру данных для удовлетворения требований.

Ответы [ 14 ]

239 голосов
/ 02 октября 2009

Карты не упорядочены, поэтому нет такой вещи, как «первая запись», и поэтому также нет метода get-by-index для 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() не означает, что вы выполняете итерацию по всей карте.

89 голосов
/ 02 октября 2009

Ответ Джеспера хорош. Другим решением является использование TreeMap (вы запрашивали другие структуры данных).

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

TreeMap имеет накладные расходы, поэтому HashMap работает быстрее, но только в качестве примера альтернативного решения.

28 голосов
/ 02 октября 2009

Я думаю, что итератор может быть самым простым решением.

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

Другое решение (не симпатичное):

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

Или еще (не лучше):

return hashMapObject.entrySet().toArray()[0];
13 голосов
/ 30 января 2012

Получить значения, преобразовать их в массив, получить первый элемент массива:

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

W.

8 голосов
/ 02 октября 2009

Почему вы хотите избежать вызова entrySet(), он не обычно создает совершенно новый объект со своим собственным контекстом, а вместо этого просто предоставляет объект фасада. Проще говоря, entrySet() - довольно дешевая операция.

7 голосов
/ 01 марта 2016

Если вы используете Java 8, это просто: findFirst () :

Быстрый пример:

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

if(theCarFoundOpt.isPresent()) {
    return theCarFoundOpt.get().startEngine();
}
6 голосов
/ 02 октября 2009

Если вы действительно хотите 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 голосов
/ 05 июля 2012
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 будет правильным решением в этом случае.

4 голосов
/ 02 октября 2009

Что вы подразумеваете под "без итерации"?

Вы можете использовать map.entrySet().iterator().next(), и вы не будете выполнять итерации по карте (в смысле «касаться каждого объекта»). Вы не можете получить Entry<K, V> без использования итератора. Javadoc Map.Entry говорит:

Метод Map.entrySet возвращает коллекционный вид карты, у которой элементы этого класса. Единственный способ получить ссылку на карту запись от итератора этого Коллекция ракурса. Эти Map.Entry объекты действительны только для продолжительность итерации.

Можете ли вы объяснить более подробно, что вы пытаетесь достичь? Если вы хотите сначала обработать объекты, которые соответствуют определенному критерию (например, «иметь определенный ключ») и в противном случае отступить к остальным объектам, тогда посмотрите на PriorityQueue . Он упорядочит ваши объекты в соответствии с естественным порядком или заданным пользователем Comparator.

3 голосов
/ 02 октября 2009

Это получило бы одну запись с карты, которая настолько близко, насколько это возможно, учитывая, что 'first' на самом деле не применяется.

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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...