问题
I need to enter key-value pairs into a data structure that allows me to retrieve them in ascending order of the key--BUT their may be many keys of the same value.
Thus, if the kv-pairs were {10-a, 10-b, 9-c, 8-d, 8-e, 8-f, 4-g, 4-h, 2-i} I would need to retrieve the values in the order: a, b ,c, d, e, f, g, h, i. Are there any data structures in the JAVA API that supports this?
I tried using a TreeMap because it kept them in order which allowed me to use TreeMap.lastKey() to retrieve the highest current key, but I didn't know that it overwrote any duplicate keys that were already in the map. I need something that doesn't overwrite (similar to a HASH), but also allows me to retrieve them in a sorted order--does this exist?
Thank you!
回答1:
Unfortunately you probably will not find a structure that supports multiple values of the same keys. As Dilum said, there are several implementations of "MultiMap" or "Multi-Valued Maps" that would work well.
In addition to Guava's TreeMultiMap, there's also the Spring Framework's MultiValueMap and Apache Common's MultiValueMap.
An example of the Spring implementation would be:
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]}
}
}
You could use this by adding Spring-Core via the following Maven dependency:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
If you need help getting any of these libs in your project, feel free to comment / contact me.
Update 1
Turns out there's not a convenient way to filter / sort from the raw API's. I've included a simple filter function below that should do the trick.
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;
}
}
回答2:
The term that is usually used in Java is 'MultiMap'. For example, look at Guava's TreeMultiMap
Neither the interface nor any implementation is part of that standard APIs.
来源:https://stackoverflow.com/questions/15182820/java-data-structure-that-acts-like-treemap-hash