- 最简单的场景, 我有这么个对象集合, 为了代码简洁, 示例均不考虑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, L))); 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}}}
实际的业务场景是公司的财务系统中, 会从各种层级维度来设置税率相关的信息, 在查找税率时会产生类似示例代码的场景.