除了使用 Java 8 的 Stream API,还可以使用传统的循环方式来在保留现有值的同时统计重复 key 的出现次数。以下为你详细介绍几种实现方法:

1. 使用普通 for 循环

可以通过遍历列表,手动维护两个 Map:一个用于存储每个键对应的首次出现的对象,另一个用于统计每个键的出现次数。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Item {
    private String key;
    private String value;

    public Item(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "Item{key='" + key + "', value='" + value + "'}";
    }
}

public class LoopBasedSolution {
    public static void main(String[] args) {
        List<Item> itemList = new ArrayList<>();
        itemList.add(new Item("A", "Value1"));
        itemList.add(new Item("B", "Value2"));
        itemList.add(new Item("A", "Value3"));

        // 用于存储每个键对应的首次出现的对象
        Map<String, Item> itemMap = new HashMap<>();
        // 用于统计每个键的出现次数
        Map<String, Integer> keyCountMap = new HashMap<>();

        for (Item item : itemList) {
            String key = item.getKey();
            // 统计键的出现次数
            keyCountMap.put(key, keyCountMap.getOrDefault(key, 0) + 1);
            // 保留现有值
            if (!itemMap.containsKey(key)) {
                itemMap.put(key, item);
            }
        }

        System.out.println("Key Count Map: " + keyCountMap);
        System.out.println("Item Map: " + itemMap);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
代码解释
  • 首先创建了两个 MapitemMap 用于存储每个键对应的首次出现的 Item 对象,keyCountMap 用于统计每个键的出现次数。
  • 遍历 itemList,对于每个 Item 对象,使用 getOrDefault 方法更新 keyCountMap 中对应键的计数。
  • 检查 itemMap 中是否已经存在该键,如果不存在,则将该 Item 对象存入 itemMap 中,以此保留现有值。

2. 使用迭代器

迭代器也是一种传统的遍历列表的方式,同样可以结合两个 Map 来实现需求。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

class Item {
    private String key;
    private String value;

    public Item(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "Item{key='" + key + "', value='" + value + "'}";
    }
}

public class IteratorBasedSolution {
    public static void main(String[] args) {
        List<Item> itemList = new ArrayList<>();
        itemList.add(new Item("A", "Value1"));
        itemList.add(new Item("B", "Value2"));
        itemList.add(new Item("A", "Value3"));

        Map<String, Item> itemMap = new HashMap<>();
        Map<String, Integer> keyCountMap = new HashMap<>();

        Iterator<Item> iterator = itemList.iterator();
        while (iterator.hasNext()) {
            Item item = iterator.next();
            String key = item.getKey();
            keyCountMap.put(key, keyCountMap.getOrDefault(key, 0) + 1);
            if (!itemMap.containsKey(key)) {
                itemMap.put(key, item);
            }
        }

        System.out.println("Key Count Map: " + keyCountMap);
        System.out.println("Item Map: " + itemMap);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
代码解释
  • 创建了和上面相同的两个 Map
  • 使用迭代器遍历 itemList,在遍历过程中更新 keyCountMapitemMap,逻辑与使用 for 循环时一致。

这些传统方法的核心思路都是通过遍历列表,手动维护键的计数和保留首次出现的值,虽然代码相对 Stream API 更冗长,但在某些不支持 Java 8 及以上版本的环境中是可行的解决方案。