- 最简单的场景, 我有这么个对象集合, 为了代码简洁, 示例均不考虑key冲突场景.
@Data
public class TestModel {
private Long id;
private BigDecimal taxRate;
}
我要是想构造一个id为key, taxRate为value的Map, 就很简单, 像这样.
var testModel = new ArrayList<TestModel>();
var idValueMap = testModel.stream()
.collect(Collectors.toMap(TestModel::getId, TestModel::getTaxRate));
- 突然数据结构变了, id变成了列表.
@Data
public class TestModel {
private BigDecimal taxRate;
private List<Long> ids;
}
我要是想构造的Map以ids中的每一个id为key, 怎么搞呢, 上代码.
public static void main(String[] args) {
var testModels = List.of(new TestModel(BigDecimal.ONE, List.of(1L, 2L, 3L)),
new TestModel(BigDecimal.TEN, List.of(4L, 5L, 6L)));
Map<Long, BigDecimal> idValueMap = testModels.stream()
.flatMap(tm -> tm.getIds().stream()
.map(id -> new AbstractMap.SimpleEntry<>(id, tm.getTaxRate()) {
}))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
System.out.println(idValueMap);
}
输出结果如图:
- 突然数据结构又变了, 像这样
@Data
@AllArgsConstructor
public class TestModel {
private BigDecimal taxRate;
private List<Long> ids;
private List<Long> orderIds;
}
我要构造一个Map嵌套的结构, 是这样Map<ids.id, Map<orderIds.id, value>> , 怎么搞呢, 上代码
public static void main(String[] args) {
var testModels = List.of(new TestModel(BigDecimal.ONE, List.of(1L, 2L, 3L), List.of(7L, 8L, 9L)),
new TestModel(BigDecimal.TEN, List.of(4L, 5L, 6L), List.of(17L, 18L, 19L)));
Map<Long, Map<Long, BigDecimal>> result = testModels.stream()
.flatMap(tm -> tm.getIds().stream()
.map(id -> new AbstractMap.SimpleEntry<>(id, tm.orderIds.stream()
.map(oId -> new AbstractMap.SimpleEntry<>(oId, tm.getTaxRate()))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue))
) {
}))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
System.out.println(result);
}
输出结果如图:
- 假如数据结构又变了, 像这样
@Data
@AllArgsConstructor
public class TestModel {
private List<Long> ids;
private List<Long> orderIds;
private List<TypeValue> typeValues;
@Data
static class TypeValue {
private List<String> type;
private String value;
}
}
我还是想构造一个Map, 结构呢是这样Map<id, Map<orderId, Map<type, value>>>, 如果不允许定义额外的局部变量, 怎么写? 上代码
看答案之前, 先试试自己的java基本功扎实不扎实.
public static void main(String[] args) throws JsonProcessingException {
var testModels = List.of(new TestModel(List.of(1L, 2L, 3L),
List.of(7L, 8L, 9L),
List.of(new TypeValue(List.of("a", "b", "c"), 1))),
new TestModel(List.of(4L, 5L, 6L),
List.of(17L, 18L, 19L),
List.of(new TypeValue(List.of("d", "e", "f"), 2))));
Map<Long, Map<Long, Map<String, Integer>>> result = testModels.stream().flatMap(tm -> tm.getIds().stream().map(
id -> new AbstractMap.SimpleEntry<>(id,
tm.orderIds.stream().map(oId -> new AbstractMap.SimpleEntry<>(oId,
tm.getTypeValues().stream().flatMap(
tv -> tv.getType().stream().map(
t -> new AbstractMap.SimpleEntry<>(
t,
tv.getValue()))).collect(
Collectors.toMap(
AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue)))).collect(
Collectors.toMap(AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue))) {
})).collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(result));
}
输出结果如下: 格式化后太长了, 我就不格式化了
{"1":{"7":{"a":1,"b":1,"c":1},"8":{"a":1,"b":1,"c":1},"9":{"a":1,"b":1,"c":1}},"2":{"7":{"a":1,"b":1,"c":1},"8":{"a":1,"b":1,"c":1},"9":{"a":1,"b":1,"c":1}},"3":{"7":{"a":1,"b":1,"c":1},"8":{"a":1,"b":1,"c":1},"9":{"a":1,"b":1,"c":1}},"4":{"17":{"d":2,"e":2,"f":2},"18":{"d":2,"e":2,"f":2},"19":{"d":2,"e":2,"f":2}},"5":{"17":{"d":2,"e":2,"f":2},"18":{"d":2,"e":2,"f":2},"19":{"d":2,"e":2,"f":2}},"6":{"17":{"d":2,"e":2,"f":2},"18":{"d":2,"e":2,"f":2},"19":{"d":2,"e":2,"f":2}}}
实际的业务场景是公司的财务系统中, 会从各种层级维度来设置税率相关的信息, 在查找税率时会产生类似示例代码的场景.