最近,我和一位同事讨论了在Java中将List转换为Map的最佳方法,以及这样做是否有任何具体的好处。
我想知道最佳的转换方法,如果有人能指导我,我将非常感激。
这是一个好方法吗?
List<Object[]> results;
Map<Integer, String> resultsMap = new HashMap<Integer, String>();
for (Object[] o : results) {
resultsMap.put((Integer) o[0], (String) o[1]);
}
普遍的方法
public static <K, V> Map<K, V> listAsMap(Collection<V> sourceList, ListToMapConverter<K, V> converter) {
Map<K, V> newMap = new HashMap<K, V>();
for (V item : sourceList) {
newMap.put( converter.getKey(item), item );
}
return newMap;
}
public static interface ListToMapConverter<K, V> {
public K getKey(V item);
}
根据你想要达到的目标,你会想到许多解决方案:
每个List项都是键和值
for( Object o : list ) {
map.put(o,o);
}
列表元素有一些可以查找的东西,可能是一个名称:
for( MyObject o : list ) {
map.put(o.name,o);
}
列表元素有一些可以查找的东西,并且不能保证它们是唯一的:使用google MultiMaps
for( MyObject o : list ) {
multimap.put(o.name,o);
}
将所有元素的位置作为键值:
for( int i=0; i<list.size; i++ ) {
map.put(i,list.get(i));
}
...
这取决于你想要达到什么目标。
从示例中可以看到,Map是从键到值的映射,而列表只是一系列元素,每个元素都有一个位置。所以它们不能自动兑换。
public class EmployeeDetailsFetchListToMap {
public static void main(String[] args) {
List<EmployeeDetailsFetch> list = new ArrayList<>();
list.add(new EmployeeDetailsFetch(1L, "vinay", 25000F));
list.add(new EmployeeDetailsFetch(2L, "kohli", 5000000F));
list.add(new EmployeeDetailsFetch(3L, "dhoni", 20000000F));
//adding id as key and map of id and student name
Map<Long, Map<Long, String>> map1 = list.stream()
.collect(
Collectors.groupingBy(
EmployeeDetailsFetch::getEmpId,
Collectors.toMap(
EmployeeDetailsFetch::getEmpId,
EmployeeDetailsFetch::getEmployeeName
)
)
);
System.out.println(map1);
//converting list into map of Student
//Adding id as Key and Value as Student into a map
Map<Long, EmployeeDetailsFetch> map = list.stream()
.collect(
Collectors.toMap(
EmployeeDetailsFetch::getEmpId,
EmployeeDetailsFetch -> EmployeeDetailsFetch
)
);
for(Map.Entry<Long, EmployeeDetailsFetch> m : map.entrySet()) {
System.out.println("key :" + m.getKey() + " Value : " + m.getValue());
}
}
}
Alexis已经在Java 8中使用toMap方法(keyMapper, valueMapper)发布了一个答案。根据这个方法实现的文档:
没有对类型、可变性、可序列化性或
返回Map的线程安全。
因此,如果我们对Map接口的特定实现感兴趣,例如HashMap,那么我们可以使用重载形式:
Map<String, Item> map2 =
itemList.stream().collect(Collectors.toMap(Item::getKey, //key for map
Function.identity(), // value for map
(o,n) -> o, // merge function in case of conflict with keys
HashMap::new)); // map factory - we want HashMap and not any Map implementation
虽然使用Function.identity()或i->i都可以,但似乎Function.identity()而不是i->i可能会根据这个相关的答案节省一些内存。