java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java Stream Map初始化

Java中Stream API处理Map初始化的操作方法

作者:BirdMan98

Stream API提供了多种方式来实现Map的构建、存在则更新、不存在则添加的操作,本文通过实例代码介绍Java中Stream API处理Map初始化的操作方法,感兴趣的朋友一起看看吧

当然可以! Stream API 提供了多种方式来实现 Map 的构建、存在则更新、不存在则添加的操作。以下是几种常用的方法:

1. 使用Collectors.toMap()处理重复键

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), // 重复的key
            new Person("Charlie", 35)
        );
        // 方法1: 使用toMap的合并函数来处理重复键
        Map<String, Integer> personMap = people.stream()
            .collect(Collectors.toMap(
                Person::getName,      // key映射器
                Person::getAge,       // value映射器
                (existing, newValue) -> newValue // 合并函数:新值覆盖旧值
            ));
        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. 不同的合并策略

// 合并函数的不同实现策略
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. 复杂的对象操作

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) // 重复商品,价格不同
        );
        // 按商品名称分组,计算总价值(价格*数量)
        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操作(更复杂的逻辑)

// 如果存在则更新,不存在则添加的复杂逻辑
Map<String, ProductStats> productStatsMap = products.stream()
    .collect(Collectors.toMap(
        Product::getName,
        product -> new ProductStats(1, product.getPrice() * product.getQuantity(), product.getPrice()),
        (existingStats, newStats) -> {
            // 存在则更新:数量累加,总价值累加,价格取平均值
            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的三参数版本

// 更底层的实现方式
Map<String, Integer> manualMap = products.stream()
    .collect(
        HashMap::new, // 供应商:创建新的Map
        (map, product) -> {
            // 累加器:处理每个元素
            String key = product.getName();
            int value = product.getQuantity();
            map.merge(key, value, Integer::sum); // 存在则求和,不存在则添加
        },
        HashMap::putAll // 组合器:用于并行流
    );

7. 处理并发Map

// 线程安全的ConcurrentMap
ConcurrentMap<String, Integer> concurrentMap = products.stream()
    .collect(Collectors.toConcurrentMap(
        Product::getName,
        Product::getQuantity,
        Integer::sum
    ));

8. 完整的实战示例

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)
        );
        // 按账户分组,计算余额(存款为正,取款为负)
        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
}

关键总结

  1. Collectors.toMap() 是主要工具,第三个参数是合并函数
  2. 合并函数 (oldValue, newValue) -> {...} 决定了存在时的更新策略
  3. 多种策略:覆盖、累加、取最大值、收集到列表等
  4. 线程安全:使用 toConcurrentMap() 处理并发场景
  5. 分组收集groupingBy() 用于更复杂的分组操作

Stream API 提供了非常强大的 Map 操作能力,完全可以实现"存在则更新,不存在则添加"的需求!

到此这篇关于Java中Stream API处理Map初始化的文章就介绍到这了,更多相关Java Stream API处理Map初始化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文