Структура данных Java, которая действует как TreeMap + Hash?

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

Таким образом, если бы kv-пары были {10-a, 10-b, 9-c, 8-d, 8-e, 8-f, 4-g, 4-h, 2-i}, мне нужно было бы получить значения в порядке: a, b, c, d, e, f, g, h, i. Существуют ли какие-либо структуры данных в JAVA API, поддерживающие это?

Я попытался использовать TreeMap, потому что он держал их в порядке, что позволяло мне использовать TreeMap.lastKey() для получения самого высокого текущего ключа, но я не знал, что он перезаписал любые дубликаты ключей, которые уже были на карте. Мне нужно что-то, что не перезаписывает (аналогично HASH), но также позволяет мне извлекать их в отсортированном порядке - существует ли это?

Благодарю вас!


person Community    schedule 03.03.2013    source источник
comment
Таким образом, один Map с List значениями будет соответствовать одному ключу с несколькими значениями - я думаю, что могу хранить Map в ArrayList, верно?   -  person    schedule 03.03.2013
comment
HashMap также перезаписывает повторяющиеся ключи. Я подозреваю, что вы не это имеете в виду? Кроме того, вы говорите в порядке возрастания ключей, но ваш пример в порядке убывания? Вы имели в виду убывающий порядок ключей и возрастающий порядок значений?   -  person Christoffer Hammarström    schedule 03.03.2013


Ответы (2)


К сожалению, вы, вероятно, не найдете структуры, поддерживающей несколько значений одних и тех же ключей. Как сказал Дилум, существует несколько реализаций «MultiMap» или «Multi-Valued Maps», которые будут хорошо работать.

В дополнение к TreeMultiMap от Guava. , есть также MultiValueMap Spring Framework. и MultiValueMap.

Примером реализации Spring будет:

import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;


public class MultiValueMapExample {

    public static void main(String[] args) {
        // 10-a, 10-b, 9-c, 8-d, 8-e, 8-f, 4-g, 4-h, 2-i
        MultiValueMap<Integer, String> map = new LinkedMultiValueMap<Integer, String>();
        map.add(10, "a");
        map.add(10, "b");
        map.add(9, "c");
        map.add(8, "d");
        map.add(8, "e");
        map.add(8, "f");
        map.add(8, "g");
        map.add(4, "h");
        map.add(2, "i");

        System.out.println(map.toString());
        // {10=[a, b], 9=[c], 8=[d, e, f, g], 4=[h], 2=[i]}
    }
}

Вы можете использовать это, добавив Spring-Core через следующую зависимость Maven:

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.1.1.RELEASE</version>
        </dependency>

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

Обновление 1

Оказывается, нет удобного способа фильтровать/сортировать необработанные API. Ниже я включил простую функцию фильтра, которая должна помочь.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;


public class MultiValueMapExample {

    public static void main(String[] args) {
        // 10-a, 10-b, 9-c, 8-d, 8-e, 8-f, 4-g, 4-h, 2-i
        MultiValueMap<Integer, String> map = new LinkedMultiValueMap<Integer, String>();
        map.add(8, "g");
        map.add(4, "h");
        map.add(10, "a");
        map.add(10, "b");
        map.add(9, "c");
        map.add(8, "d");
        map.add(8, "e");
        map.add(8, "f");

        map.add(2, "i");

        System.out.println(map.toString());
        // {8=[g, d, e, f], 4=[h], 10=[a, b], 9=[c], 2=[i]}

        MultiValueMap<Integer, String> filteredMap = filter(5, map);
        System.out.println( filteredMap.toString() );
        // {10=[a, b], 9=[c], 8=[g, d, e, f], 4=[h], 2=[i]}

    }

    public static MultiValueMap<Integer, String> filter(int numberOfResults, MultiValueMap<Integer, String> map){
        MultiValueMap<Integer, String> result = new LinkedMultiValueMap<Integer, String>();

        List<Integer> keys = new ArrayList<Integer>(map.keySet());
        Collections.sort(keys, Collections.reverseOrder());

        for(Integer key : keys){
            if( result.size() <= numberOfResults ){
                result.put(key, map.get(key));
            }else{
                break;
            }
        }

        return result;

    }
}
person David Welch    schedule 03.03.2013
comment
Дэвид, можно ли получить элементы в мультинаборе по порядку ключей? Например, у меня есть массив размером 5, и я хочу взять значения с 5 старшими ключами. В этом случае я бы взял a, b, c, d и e. Возможно ли это в любой из реализаций? Если это так, я был бы очень заинтересован в вашей помощи в использовании библиотеки в моем проекте, спасибо! - person ; 03.03.2013
comment
Да, вы должны иметь возможность использовать Collections.sort с сопоставимой реализацией. Вы хотите сделать это на основе самого высокого значения ключа или ключа с наибольшим количеством значений? - person David Welch; 03.03.2013
comment
Оказывается, фильтровать карты немного сложнее. Я добавил обновленный пример с простым методом фильтрации. Это должно работать достаточно хорошо, если у вас нет большого набора данных или чего-то еще. - person David Welch; 03.03.2013
comment
@kpscript помог ли вам какой-нибудь из ответов? Если да, то проголосуйте :D - person David Welch; 04.03.2013