是否可以使用一个键和两个值来实现HashMap,例如HashMap<userId,clientID,timeStamp>?
如果不行,是否有其他方法来存储多个值,例如一个键和两个值?
是否可以使用一个键和两个值来实现HashMap,例如HashMap<userId,clientID,timeStamp>?
如果不行,是否有其他方法来存储多个值,例如一个键和两个值?
你可以采取以下几种方式:
Map<KeyType, List<ValueType>>
。Map<KeyType, WrapperType>
。Map<KeyType, Tuple<Value1Type, Value2Type>>
。1. 使用列表作为值的映射表
// create our map
Map<String, List<Person>> peopleByForename = new HashMap<>();
// populate it
List<Person> people = new ArrayList<>();
people.add(new Person("Bob Smith"));
people.add(new Person("Bob Jones"));
peopleByForename.put("Bob", people);
// read from it
List<Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs[0];
Person bob2 = bobs[1];
这种方法的缺点是列表不仅限于两个值。 2. 使用包装类
// define our wrapper
class Wrapper {
public Wrapper(Person person1, Person person2) {
this.person1 = person1;
this.person2 = person2;
}
public Person getPerson1() { return this.person1; }
public Person getPerson2() { return this.person2; }
private Person person1;
private Person person2;
}
// create our map
Map<String, Wrapper> peopleByForename = new HashMap<>();
// populate it
peopleByForename.put("Bob", new Wrapper(new Person("Bob Smith"),
new Person("Bob Jones"));
// read from it
Wrapper bobs = peopleByForename.get("Bob");
Person bob1 = bobs.getPerson1();
Person bob2 = bobs.getPerson2();
这种方法的缺点是,您必须为所有这些非常简单的容器类编写大量样板代码。
3. 使用元组// you'll have to write or download a Tuple class in Java, (.NET ships with one)
// create our map
Map<String, Tuple2<Person, Person> peopleByForename = new HashMap<>();
// populate it
peopleByForename.put("Bob", new Tuple2(new Person("Bob Smith",
new Person("Bob Jones"));
// read from it
Tuple<Person, Person> bobs = peopleByForename["Bob"];
Person bob1 = bobs.Item1;
Person bob2 = bobs.Item2;
我认为这是最好的解决方案。
4. 多个地图
// create our maps
Map<String, Person> firstPersonByForename = new HashMap<>();
Map<String, Person> secondPersonByForename = new HashMap<>();
// populate them
firstPersonByForename.put("Bob", new Person("Bob Smith"));
secondPersonByForename.put("Bob", new Person("Bob Jones"));
// read from them
Person bob1 = firstPersonByForename["Bob"];
Person bob2 = secondPersonByForename["Bob"];
这种解决方案的缺点在于不容易看出这两个映射是相关的,如果出现程序错误,这两个映射可能会失去同步。Map<KeyType,Tuple<Value1Type,Value2Type>>
- Joarder KamalMultimap
实现,例如ArrayListMultimap
, HashMultimap
, LinkedHashMultimap
等。Multimap<String, Integer> nameToNumbers = HashMultimap.create();
System.out.println(nameToNumbers.put("Ann", 5)); // true
System.out.println(nameToNumbers.put("Ann", 5)); // false
nameToNumbers.put("Ann", 6);
nameToNumbers.put("Sam", 7);
System.out.println(nameToNumbers.size()); // 3
System.out.println(nameToNumbers.keySet().size()); // 2
ArrayListMultimap
类似的东西,或者使用一个HashMap<String, List<Integer>>
之类的。你需要在第一次添加值时创建一个空列表。 - Jon SkeetHashMap<String, List<Integer>>
的工作示例吗? - DeepakHashMap<K, ArrayList<String>> map = new HashMap<K, ArrayList<String>>()
可以被替换为
MultiValuedMap<K, String> map = new MultiValuedHashMap<K, String>();
所以,
map.put(key, "A");
map.put(key, "B");
map.put(key, "C");
Collection<String> coll = map.get(key);
会导致集合coll
包含"A"、"B"和"C"。
看一下 guava-libraries 的 Multimap
及其实现方式 - HashMultimap
Multimap
是类似于Map的集合,但是可以将多个值与一个键相关联。如果您使用相同的键但不同的值两次调用put(K,V),则 multimap 包含从该键到这两个值的映射。
我在Map中使用Map<KeyType, Object[]>
,以将多个值与一个键关联。这样,我就可以存储不同类型的多个值与一个键相关联。您需要注意维护插入和从Object[]检索的正确顺序。
例如: 考虑我们要存储学生信息。键是id,而我们希望将姓名、地址和电子邮件与学生关联存储。
//To make entry into Map
Map<Integer, String[]> studenMap = new HashMap<Integer, String[]>();
String[] studentInformationArray = new String[]{"name", "address", "email"};
int studenId = 1;
studenMap.put(studenId, studentInformationArray);
//To retrieve values from Map
String name = studenMap.get(studenId)[1];
String address = studenMap.get(studenId)[2];
String email = studenMap.get(studenId)[3];
org.springframework.util.MultiValueMap
。要创建一个不可修改的多值映射,请按如下方式操作:Map<String,List<String>> map = ...
MultiValueMap<String, String> multiValueMap = CollectionUtils.toMultiValueMap(map);
或者使用org.springframework.util.LinkedMultiValueMap
HashMap<Integer,ArrayList<String>> map = new HashMap<Integer,ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("xyz");
map.put(100,list);
最简单的方法是使用 Google 的集合库:
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class Test {
public static void main(final String[] args) {
// multimap can handle one key with a list of values
final Multimap<String, String> cars = ArrayListMultimap.create();
cars.put("Nissan", "Qashqai");
cars.put("Nissan", "Juke");
cars.put("Bmw", "M3");
cars.put("Bmw", "330E");
cars.put("Bmw", "X6");
cars.put("Bmw", "X5");
cars.get("Bmw").forEach(System.out::println);
// It will print the:
// M3
// 330E
// X6
// X5
}
}
maven链接:https://mvnrepository.com/artifact/com.google.collections/google-collections/1.0-rc2
更多信息请查阅:http://tomjefferys.blogspot.be/2011/09/multimaps-google-guava.html
只是为了记录,纯JDK8解决方案是使用Map::compute
方法:
map.compute(key, (s, strings) -> strings == null ? new ArrayList<>() : strings).add(value);
public static void main(String[] args) {
Map<String, List<String>> map = new HashMap<>();
put(map, "first", "hello");
put(map, "first", "foo");
put(map, "bar", "foo");
put(map, "first", "hello");
map.forEach((s, strings) -> {
System.out.print(s + ": ");
System.out.println(strings.stream().collect(Collectors.joining(", ")));
});
}
private static <KEY, VALUE> void put(Map<KEY, List<VALUE>> map, KEY key, VALUE value) {
map.compute(key, (s, strings) -> strings == null ? new ArrayList<>() : strings).add(value);
}
输出结果:
bar: foo
first: hello, foo, hello
请注意,为了确保多个线程访问此数据结构的一致性,例如需要使用ConcurrentHashMap
和CopyOnWriteArrayList
。
computeIfAbsent
。map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
- user4910279