You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中初始化ArrayList等对象时,何时应该使用菱形运算符<>?

问题根因

你遇到的编译报错本质和钻石运算符<>的使用无关,根源是你定义的Map使用了原始泛型类型丢失了类型信息:
你声明的Map是Map<String, List> res = new HashMap<>(),这里的List没有指定泛型参数,属于Java的原始类型(Raw Type),此时res.values()返回的集合类型是Collection<List>,而你要构造的ArrayList<List<String>>要求入参必须是Collection<? extends List<String>>,二者类型不匹配所以编译失败。

你使用new ArrayList(map.values())能正常运行,是因为你主动用了原始类型的ArrayList,跳过了编译期的泛型类型校验,本质是牺牲了类型安全换编译通过,只是你的业务逻辑中所有List存储的都是String元素,才没有触发运行时类型转换异常。

泛型<>的使用规则

Java 7及以上版本引入的钻石运算符<>作用是简化泛型声明,只要编译器可以从上下文推断出泛型参数类型,就可以用<>省略右侧的类型声明,规则如下:

  • 优先保证所有泛型类型的声明都指定完整参数,不要主动使用原始类型。你的场景只需要把Map的声明调整为Map<String, List<String>> res = new HashMap<>(),存入元素时的new ArrayList()改为new ArrayList<>(),后续return new ArrayList<>(res.values())就可以正常编译,同时保留类型安全校验。
  • 当编译器可以从左侧变量声明、方法返回值要求等上下文推断出泛型类型时,可以直接用<>省略参数,比如List<String> list = new ArrayList<>() 编译器可以从左侧声明推断出泛型为String,无需重复写。
  • 当没有足够上下文供编译器推断类型时,需要显式指定泛型参数,比如直接用var声明变量时,var list = new ArrayList<String>() 必须指定参数,否则编译器会默认推断为ArrayList<Object>。
  • 除非需要兼容Java 5之前的老代码,否则绝对不要主动使用不带<>的原始泛型写法,原始类型会跳过所有泛型校验,很容易埋下运行时ClassCastException隐患。
修正后的可编译代码
public List<List<String>> groupAnagrams(String[] strs) {
    if (strs.length == 0) return new ArrayList<>();
    Map<String, List<String>> res = new HashMap<>();
    for (String s : strs) {
        char[] charArray = s.toCharArray();
        Arrays.sort(charArray);
        String key = String.valueOf(charArray);
        if (!res.containsKey(key)) res.put(key, new ArrayList<>());
        res.get(key).add(s);
    }
    return new ArrayList<>(res.values());
}

内容的提问来源于stack exchange,提问作者user15064722

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:39:03