Java 8 – Convert List to Map

本文详细介绍如何使用Java8的Stream API将List转换为Map,包括处理重复键、选择旧值或新值以及按特定顺序收集和排序Map的示例。

Java 8 – Convert List to Map

package com.mkyong.java8

public class Hosting {

private int Id;
private String name;
private long websites;

public Hosting(int id, String name, long websites) {
Id = id;
this.name = name;
this.websites = websites;
}

//getters, setters and toString()
}

1. List to Map – Collectors.toMap()
package com.mkyong.java8

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestListMap {

public static void main(String[] args) {

List<Hosting> list = new ArrayList<>();
list.add(new Hosting(1, "liquidweb.com", 80000));
list.add(new Hosting(2, "linode.com", 90000));
list.add(new Hosting(3, "digitalocean.com", 120000));
list.add(new Hosting(4, "aws.amazon.com", 200000));
list.add(new Hosting(5, "mkyong.com", 1));

// key = id, value - websites
Map<Integer, String> result1 = list.stream().collect(
Collectors.toMap(Hosting::getId, Hosting::getName));

System.out.println("Result 1 : " + result1);

// key = name, value - websites
Map<String, Long> result2 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites));

System.out.println("Result 2 : " + result2);

// Same with result1, just different syntax
// key = id, value = name
Map<Integer, String> result3 = list.stream().collect(
Collectors.toMap(x -> x.getId(), x -> x.getName()));

System.out.println("Result 3 : " + result3);
}
}

Output

Result 1 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com}
Result 2 : {liquidweb.com=80000, mkyong.com=1, digitalocean.com=120000, aws.amazon.com=200000, linode.com=90000}
Result 3 : {1=liquidweb.com, 2=linode.com, 3=digitalocean.com, 4=aws.amazon.com, 5=mkyong.com}


2. List to Map – Duplicated Key!
package com.mkyong.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestDuplicatedKey {

public static void main(String[] args) {

List<Hosting> list = new ArrayList<>();
list.add(new Hosting(1, "liquidweb.com", 80000));
list.add(new Hosting(2, "linode.com", 90000));
list.add(new Hosting(3, "digitalocean.com", 120000));
list.add(new Hosting(4, "aws.amazon.com", 200000));
list.add(new Hosting(5, "mkyong.com", 1));

list.add(new Hosting(6, "linode.com", 100000)); // new line

// key = name, value - websites , but the key 'linode' is duplicated!?
Map<String, Long> result1 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites));

System.out.println("Result 1 : " + result1);

}
}

Output – The error message below is a bit misleading, it should show “linode” instead of the value of the key.

Exception in thread "main" java.lang.IllegalStateException: Duplicate key 90000
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1245)
//...

2.2 To solve the duplicated key issue above, pass in the third mergeFunction argument like this :

Map<String, Long> result1 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites,
(oldValue, newValue) -> oldValue
)
);

Output

Result 1 : {..., aws.amazon.com=200000, linode.com=90000}
Copy
Note
(oldValue, newValue) -> oldValue ==> If the key is duplicated, do you prefer oldKey or newKey?

3.3 Try newValue

Map<String, Long> result1 = list.stream().collect(
Collectors.toMap(Hosting::getName, Hosting::getWebsites,
(oldValue, newValue) -> newvalue
)
);

Output

Result 1 : {..., aws.amazon.com=200000, linode.com=100000}

3. List to Map – Sort & Collect
package com.mkyong.java8;

import java.util.*;
import java.util.stream.Collectors;

public class TestSortCollect {

public static void main(String[] args) {

List<Hosting> list = new ArrayList<>();
list.add(new Hosting(1, "liquidweb.com", 80000));
list.add(new Hosting(2, "linode.com", 90000));
list.add(new Hosting(3, "digitalocean.com", 120000));
list.add(new Hosting(4, "aws.amazon.com", 200000));
list.add(new Hosting(5, "mkyong.com", 1));
list.add(new Hosting(6, "linode.com", 100000));

//example 1
Map result1 = list.stream()
.sorted(Comparator.comparingLong(Hosting::getWebsites).reversed())
.collect(
Collectors.toMap(
Hosting::getName, Hosting::getWebsites, // key = name, value = websites
(oldValue, newValue) -> oldValue, // if same key, take the old key
LinkedHashMap::new // returns a LinkedHashMap, keep order
));

System.out.println("Result 1 : " + result1);

}
}

Result 1 : {aws.amazon.com=200000, digitalocean.com=120000, linode.com=100000, liquidweb.com=80000, mkyong.com=1}

http://www.mkyong.com/java8/java-8-convert-list-to-map/

Java中,将实体类的`List`转换为`Map`的`List`通常涉及将每个实体对象转换为一个`Map`,其中键是字段名称,值是字段内容。这种操作可以通过Java内置的类库实现,也可以使用第三方库如`Apache Commons BeanUtils`或`Dozer`简化映射过程。 一种常见的方式是使用Java 8的流(`Stream`)和`Collectors.toMap`方法来实现转换。例如,假设有一个表示地址的实体类`Address`,包含`id`、`addtime`、`userid`、`address`、`name`、`phone`和`isdefault`字段[^3],可以使用如下方式将其转换为`Map`列表: ```java import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Address> addressList = Arrays.asList( new Address(1L, new Date(), 1001L, "Main St", "Alice", "1234567890", "是"), new Address(2L, new Date(), 1002L, "Elm St", "Bob", "0987654321", "否") ); List<Map<String, Object>> mapList = addressList.stream() .map(Address::toMap) .collect(Collectors.toList()); System.out.println(mapList); } } class Address { private Long id; private Date addtime; private Long userid; private String address; private String name; private String phone; private String isdefault; // 构造函数、getter和setter省略 public Map<String, Object> toMap() { Map<String, Object> map = new HashMap<>(); map.put("id", id); map.put("addtime", addtime); map.put("userid", userid); map.put("address", address); map.put("name", name); map.put("phone", phone); map.put("isdefault", isdefault); return map; } } ``` 上述代码中,每个`Address`实例都有一个`toMap`方法用于将对象属性转换为`Map`。通过`stream()`和`map()`方法,可以将整个`List<Address>`转换为`List<Map<String, Object>>`。 如果实体类较多或字段复杂,可以考虑使用反射来自动提取字段值,从而避免手动编写`toMap`方法。例如,使用`java.lang.reflect.Field`来遍历所有字段并提取值: ```java public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException { Map<String, Object> map = new HashMap<>(); for (Field field : obj.getClass().getDeclaredFields()) { field.setAccessible(true); map.put(field.getName(), field.get(obj)); } return map; } ``` 通过这种方式,可以动态地将任意对象转换为`Map`,并应用于整个`List`。 ### 性能优化与库支持 对于大量数据的转换,直接使用反射可能会导致性能问题。此时可以考虑使用`Jackson`或`Gson`等序列化库,它们内部优化了字段访问和类型转换过程,适用于高性能场景。例如,使用`Jackson`将对象转换为`Map`: ```java import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper mapper = new ObjectMapper(); Map<String, Object> map = mapper.convertValue(obj, Map.class); ``` 这种方法可以有效提升转换效率,并减少手动编码的工作量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值