假設(shè)需求時這樣的
將一個對象list轉(zhuǎn)換成map
// 原數(shù)據(jù):
List<Order> orders;
// 轉(zhuǎn)換后數(shù)據(jù):
Map<Long, String> orderMaps;
list里的元素

轉(zhuǎn)換后map的key-value

現(xiàn)階段的解決方式一般有2大類
- java代碼里顯示使用for循環(huán)
- 通過stream的內(nèi)循環(huán)
先寫簡單的方案,顯示for循環(huán)如下
// 我不寫了,這個太簡單了
再來寫stream的方案
- 通過集合類型的.stream()函數(shù)將集合轉(zhuǎn)成流,
- 然后通過collect()函數(shù)收集流數(shù)據(jù),
- 此函數(shù)的參數(shù)是Collectors.toXXX();
代碼如下:
準(zhǔn)備工作1,這是模擬的訂單類,湊合一下
/**
* 模擬訂單類
*/
@Data
@AllArgsConstructor
@Accessors(chain = true)
class Order {
private Long id;
private String receiverName;
}
準(zhǔn)備工作2,準(zhǔn)備一個訂單集合
static List<Order> buildOrders() {
Order order1 = new Order(1L, "李靜");
Order order2 = new Order(2L, "沙坪");
Order order3 = new Order(3L, "老李");
List<Order> orders = new ArrayList<>(3);
orders.add(order1);
orders.add(order2);
orders.add(order3);
return orders;
}
處理工作,將list轉(zhuǎn)成map
先來寫個簡易版本
// 方式1, 簡易版
Map<Long, String> map2 = orders.stream().collect(Collectors.toMap(
kv -> { // 處理key的函數(shù)
return kv.getId();
},
kv -> { // 處理value的函數(shù)
return kv.getReceiverName();
}));
// 觀察返回map的類型
System.out.println(map2.getClass());
map2.forEach((k, v) -> {
System.out.println(k + "-" + v);
});
執(zhí)行結(jié)果如下:可以發(fā)現(xiàn)返回map的類型是java.util.HashMap
class java.util.HashMap
1-李靜
2-沙坪
3-老李
再來寫一個進(jìn)階版本,這是看阿里開發(fā)手冊發(fā)現(xiàn)的
因為原集合轉(zhuǎn)換成map的過程中,有可能會出現(xiàn)key重復(fù),為了解決key重復(fù),所以Collectors.toMap函數(shù)提供了重載方法,第三個參數(shù)函數(shù)用于處理key重復(fù)
方式2,進(jìn)階版
Map<Long, String> map3 = orders.stream().collect(Collectors.toMap(
kv -> {
return kv.getId();
},
kv -> {
return kv.getReceiverName();
},
(oldKey, newKey) -> { // 處理key重復(fù)的函數(shù)
System.err.println("key重復(fù),已替換");
return newKey;
}));
System.out.println(map3.getClass());
map3.forEach((k, v) -> {
System.out.println(k + "-" + v);
});
執(zhí)行之前做下修改:
這里需要先將原集合,即order集合里的元素值改成如下內(nèi)容,order2與order3的id都是2L,這樣會出現(xiàn)key重復(fù)
Order order1 = new Order(1L, "李靜");
Order order2 = new Order(2L, "沙坪");
Order order3 = new Order(2L, "老李");
執(zhí)行結(jié)果如下:
- 簡易版的執(zhí)行結(jié)果:很顯然的報出了key重復(fù)的異常
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 沙坪
at java.util.stream.Collectors.lambda0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1254)
at java.util.stream.Collectors.lambda58(Collectors.java:1320)
at java.util.stream.ReduceOpsArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.enn.sale.crm.clue.web.Test.main(Test.java:39)
- 進(jìn)階版本執(zhí)行結(jié)果:沒啥問題,重復(fù)的key已經(jīng)按照代碼內(nèi)容處理了,返回map類型依然是java.util.HashMap
class java.util.HashMap
1-李靜
2-老李
再寫一個增強(qiáng)版本吧
這個版本的目的是,指定轉(zhuǎn)換后map類型,比如我不想用HashMap,我可以指定為TreeMap
Map<Long, String> map4 = orders.stream().collect(Collectors.toMap(
kv -> {
return kv.getId();
},
kv -> {
return kv.getReceiverName();
},
(oldKey, newKey) -> {
System.err.println("key重復(fù),已替換");
return newKey;
},
() -> {
// 此處是個提供者類型的函數(shù)式接口,不用參數(shù),只返回
// 返回值為指定轉(zhuǎn)換后map的類型的對象
// 源碼注釋是這樣的,自己體會吧
// a function which returns a new, empty {@code Map} into
// * which the results will be inserted
return new TreeMap<>();
}
));
System.out.println(map4.getClass());
map4.forEach((k, v) -> {
System.out.println(k + "-" + v);
});
執(zhí)行結(jié)果如下:返回類型已經(jīng)是java.util.TreeMap
class java.util.TreeMap
1-李靜
2-老李
本篇內(nèi)容基本上寫完了,建議在開發(fā)中盡量不要使用簡易版本,key重復(fù)這種情況很難避免
粘貼下1.8的部分源碼
/**
* @param keyMapper a mapping function to produce keys
* @param valueMapper a mapping function to produce values
* @param mergeFunction a merge function, used to resolve collisions between
* values associated with the same key, as supplied
* to {@link Map#merge(Object, Object, BiFunction)}
* @param mapSupplier a function which returns a new, empty {@code Map} into
* which the results will be inserted
* @return a {@code Collector} which collects elements into a {@code Map}
* whose keys are the result of applying a key mapping function to the input
* elements, and whose values are the result of applying a value mapping
* function to all input elements equal to the key and combining them
* using the merge function
*
* @see #toMap(Function, Function)
* @see #toMap(Function, Function, BinaryOperator)
* @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
*/
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier)
寫完收工