像TreeMap + Hash一样的Java数据结构?

时间:2013-03-03 05:39:23

标签: java list data-structures hashmap treemap

我需要将键值对输入数据结构,允许我按键的升序检索它们 - 但它们可能是许多具有相同值的键。

因此,如果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),但也允许我按排序顺序检索它们 - 这是否存在?

谢谢!

2 个答案:

答案 0 :(得分:1)

Java中通常使用的术语是“MultiMap”。例如,请查看Guava's TreeMultiMap

接口和任何实现都不是标准API的一部分。

答案 1 :(得分:1)

不幸的是,您可能找不到支持相同键的多个值的结构。正如Dilum所说,“MultiMap”或“多值映射”的几种实现方式都可以正常运行。

除了Guava的TreeMultiMap之外,还有Spring Framework的MultiValueMap和Apache Common的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]}
    }
}

您可以通过以下Maven依赖项添加Spring-Core来使用它:

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

    }
}