Java中Stream API處理Map初始化的操作方法
當(dāng)然可以! Stream API 提供了多種方式來實(shí)現(xiàn) Map 的構(gòu)建、存在則更新、不存在則添加的操作。以下是幾種常用的方法:
1. 使用Collectors.toMap()處理重復(fù)鍵
import java.util.*;
import java.util.stream.Collectors;
public class StreamMapOperations {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 25),
new Person("Bob", 30),
new Person("Alice", 28), // 重復(fù)的key
new Person("Charlie", 35)
);
// 方法1: 使用toMap的合并函數(shù)來處理重復(fù)鍵
Map<String, Integer> personMap = people.stream()
.collect(Collectors.toMap(
Person::getName, // key映射器
Person::getAge, // value映射器
(existing, newValue) -> newValue // 合并函數(shù):新值覆蓋舊值
));
System.out.println("覆蓋策略: " + personMap);
// 輸出: {Alice=28, Bob=30, Charlie=35}
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}2. 不同的合并策略
// 合并函數(shù)的不同實(shí)現(xiàn)策略
Map<String, Integer> map1 = people.stream()
.collect(Collectors.toMap(
Person::getName,
Person::getAge,
(oldValue, newValue) -> oldValue // 保留舊值
));
Map<String, Integer> map2 = people.stream()
.collect(Collectors.toMap(
Person::getName,
Person::getAge,
(oldValue, newValue) -> oldValue + newValue // 求和
));
Map<String, List<Integer>> map3 = people.stream()
.collect(Collectors.toMap(
Person::getName,
person -> new ArrayList<>(Arrays.asList(person.getAge())),
(oldList, newList) -> {
oldList.addAll(newList);
return oldList;
}
));
System.out.println("保留舊值: " + map1); // {Alice=25, Bob=30, Charlie=35}
System.out.println("求和: " + map2); // {Alice=53, Bob=30, Charlie=35}
System.out.println("收集所有值: " + map3); // {Alice=[25, 28], Bob=[30], Charlie=[35]}3. 復(fù)雜的對象操作
class Product {
private String category;
private String name;
private double price;
private int quantity;
public Product(String category, String name, double price, int quantity) {
this.category = category;
this.name = name;
this.price = price;
this.quantity = quantity;
}
// getters
public String getCategory() { return category; }
public String getName() { return name; }
public double getPrice() { return price; }
public int getQuantity() { return quantity; }
}
public class ComplexMapOperations {
public static void main(String[] args) {
List<Product> products = Arrays.asList(
new Product("Electronics", "Laptop", 1000, 2),
new Product("Electronics", "Phone", 500, 5),
new Product("Books", "Novel", 20, 10),
new Product("Electronics", "Laptop", 900, 3) // 重復(fù)商品,價格不同
);
// 按商品名稱分組,計算總價值(價格*數(shù)量)
Map<String, Double> productValueMap = products.stream()
.collect(Collectors.toMap(
Product::getName,
product -> product.getPrice() * product.getQuantity(),
Double::sum // 存在則累加
));
System.out.println("商品總價值: " + productValueMap);
// 輸出: {Laptop=4700.0, Phone=2500.0, Novel=200.0}
}
}4. 分組收集器的高級用法
// 按類別分組,并收集每個類別的商品列表
Map<String, List<Product>> productsByCategory = products.stream()
.collect(Collectors.groupingBy(Product::getCategory));
// 按類別分組,并計算每個類別的總價值
Map<String, Double> categoryTotalValue = products.stream()
.collect(Collectors.groupingBy(
Product::getCategory,
Collectors.summingDouble(p -> p.getPrice() * p.getQuantity())
));
// 按類別分組,并獲取每個類別最貴的商品
Map<String, Optional<Product>> mostExpensiveByCategory = products.stream()
.collect(Collectors.groupingBy(
Product::getCategory,
Collectors.maxBy(Comparator.comparingDouble(Product::getPrice))
));
System.out.println("按類別分組: " + productsByCategory.keySet());
System.out.println("類別總價值: " + categoryTotalValue);5. 自定義Map操作(更復(fù)雜的邏輯)
// 如果存在則更新,不存在則添加的復(fù)雜邏輯
Map<String, ProductStats> productStatsMap = products.stream()
.collect(Collectors.toMap(
Product::getName,
product -> new ProductStats(1, product.getPrice() * product.getQuantity(), product.getPrice()),
(existingStats, newStats) -> {
// 存在則更新:數(shù)量累加,總價值累加,價格取平均值
int totalCount = existingStats.getCount() + newStats.getCount();
double totalValue = existingStats.getTotalValue() + newStats.getTotalValue();
double avgPrice = totalValue / (existingStats.getCount() + newStats.getCount());
return new ProductStats(totalCount, totalValue, avgPrice);
}
));
class ProductStats {
private int count;
private double totalValue;
private double averagePrice;
public ProductStats(int count, double totalValue, double averagePrice) {
this.count = count;
this.totalValue = totalValue;
this.averagePrice = averagePrice;
}
// getters and toString
}6. 使用collect的三參數(shù)版本
// 更底層的實(shí)現(xiàn)方式
Map<String, Integer> manualMap = products.stream()
.collect(
HashMap::new, // 供應(yīng)商:創(chuàng)建新的Map
(map, product) -> {
// 累加器:處理每個元素
String key = product.getName();
int value = product.getQuantity();
map.merge(key, value, Integer::sum); // 存在則求和,不存在則添加
},
HashMap::putAll // 組合器:用于并行流
);7. 處理并發(fā)Map
// 線程安全的ConcurrentMap
ConcurrentMap<String, Integer> concurrentMap = products.stream()
.collect(Collectors.toConcurrentMap(
Product::getName,
Product::getQuantity,
Integer::sum
));
8. 完整的實(shí)戰(zhàn)示例
public class CompleteMapExample {
public static void main(String[] args) {
List<Transaction> transactions = Arrays.asList(
new Transaction("ACC001", "DEPOSIT", 1000),
new Transaction("ACC001", "WITHDRAW", 200),
new Transaction("ACC002", "DEPOSIT", 500),
new Transaction("ACC001", "DEPOSIT", 300),
new Transaction("ACC003", "DEPOSIT", 1500)
);
// 按賬戶分組,計算余額(存款為正,取款為負(fù))
Map<String, Double> accountBalances = transactions.stream()
.collect(Collectors.toMap(
Transaction::getAccountNumber,
transaction -> {
double amount = transaction.getAmount();
if ("WITHDRAW".equals(transaction.getType())) {
amount = -amount;
}
return amount;
},
Double::sum // 存在則累加余額
));
System.out.println("賬戶余額:");
accountBalances.forEach((account, balance) ->
System.out.println(account + ": " + balance)
);
}
}
class Transaction {
private String accountNumber;
private String type;
private double amount;
public Transaction(String accountNumber, String type, double amount) {
this.accountNumber = accountNumber;
this.type = type;
this.amount = amount;
}
// getters
}關(guān)鍵總結(jié)
Collectors.toMap()是主要工具,第三個參數(shù)是合并函數(shù)- 合并函數(shù)
(oldValue, newValue) -> {...}決定了存在時的更新策略 - 多種策略:覆蓋、累加、取最大值、收集到列表等
- 線程安全:使用
toConcurrentMap()處理并發(fā)場景 - 分組收集:
groupingBy()用于更復(fù)雜的分組操作
Stream API 提供了非常強(qiáng)大的 Map 操作能力,完全可以實(shí)現(xiàn)"存在則更新,不存在則添加"的需求!
到此這篇關(guān)于Java中Stream API處理Map初始化的文章就介紹到這了,更多相關(guān)Java Stream API處理Map初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloud?中防止繞過網(wǎng)關(guān)請求直接訪問后端服務(wù)的解決方法
這篇文章主要介紹了SpringCloud中如何防止繞過網(wǎng)關(guān)請求直接訪問后端服務(wù),本文給大家分享三種解決方案,需要的朋友可以參考下2023-06-06
使用Java動態(tài)創(chuàng)建Flowable會簽?zāi)P偷氖纠a
動態(tài)創(chuàng)建流程模型,尤其是會簽(Parallel Gateway)模型,是提升系統(tǒng)靈活性和響應(yīng)速度的關(guān)鍵技術(shù)之一,本文將通過Java編程語言,深入探討如何在運(yùn)行時動態(tài)地創(chuàng)建包含會簽環(huán)節(jié)的Flowable流程模型,需要的朋友可以參考下2024-05-05
Spring Security基于數(shù)據(jù)庫的ABAC屬性權(quán)限模型實(shí)戰(zhàn)開發(fā)教程
這篇文章主要介紹了Spring Security基于數(shù)據(jù)庫的ABAC屬性權(quán)限模型實(shí)戰(zhàn)開發(fā)教程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2025-04-04
MyBatis-Plus中AutoGenerator的使用案例
AutoGenerator是MyBatis-Plus的代碼生成器,通過?AutoGenerator?可以快速生成?Pojo、Mapper、?Mapper?XML、Service、Controller?等各個模塊的代碼,這篇文章主要介紹了MyBatis-Plus中AutoGenerator的詳細(xì)使用案例,需要的朋友可以參考下2023-05-05
關(guān)于SpringBoot創(chuàng)建存儲令牌的媒介類和過濾器的問題
這篇文章主要介紹了SpringBoot創(chuàng)建存儲令牌的媒介類和過濾器的問題,需要在配置文件中,添加JWT需要的密匙,過期時間和緩存過期時間,具體實(shí)例代碼參考下本文2021-09-09
使用Jenkins來構(gòu)建GIT+Maven項(xiàng)目的方法步驟
這篇文章主要介紹了使用Jenkins來構(gòu)建GIT+Maven項(xiàng)目,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Java使用connectTo方法提高代碼可續(xù)性詳解
這篇文章主要介紹了Java使用connectTo方法提高代碼可續(xù)性,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
基于springboot bean的實(shí)例化過程和屬性注入過程
這篇文章主要介紹了基于springboot bean的實(shí)例化過程和屬性注入過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11

