【问题标题】:Why does EnumSet have many overloaded "of" methods?为什么 EnumSet 有许多重载的“of”方法?
【发布时间】:2015-11-02 15:27:58
【问题描述】:

在通过EnumSet<E>of方法时,我看到of方法的多个重载实现:

public static <E extends Enum<E>> EnumSet<E> of(E e)

public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2)

.
.

public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5)

然后是varargs的另一个重载方法

public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
    EnumSet<E> result = noneOf(first.getDeclaringClass());
    result.add(first);
    for (E e : rest)
        result.add(e);
    return result;
}

当这个可变参数可以处理其他实现时,为什么这个方法会以这种方式重载?这有什么具体原因吗?

我浏览过同样的Javadoc,但找不到任何令人信服的解释。

【问题讨论】:

  • 看起来它只是针对速度进行了优化。
  • 优化到像 EnumSet 这样的位集合以作为枚举重新获得某些东西是非常基本的,但在 java 中枚举不仅仅是一个命名数字,
  • 可以几乎被视为stackoverflow.com/questions/3737882/…的副本...

标签: java collections enumset


【解决方案1】:

可变参数方法创建一个数组。

public static void foo(Object... args) {
  System.out.println(args.length);
}

这是可行的,因为隐式数组创建。 EnumSet 是一个设计得非常非常快的类,因此通过创建所有额外的重载,它们可以在最初的几种情况下跳过数组创建步骤。尤其如此,因为在许多情况下,Enum 没有那么多元素,如果有,EnumSet 可能不会包含所有元素。

Javadoc for EnumSet&lt;E&gt; of(E e1, E e2, E e3, E e4, E e5):

创建一个最初包含指定元素的枚举集。存在此方法的重载以初始化具有一到五个元素的枚举集。提供了使用可变参数功能的第六个重载。此重载可用于创建最初包含任意数量元素的枚举集,但可能比不使用可​​变参数的重载运行得更慢。

【讨论】:

    【解决方案2】:

    varags 创建一个数组,也就是我们调用的时候

    void x(int...x) {...}
    ..
    x(1);
    

    编译器将最后一行替换为:

    x(new int[] {1});
    

    如果我们有一个带有 1 个参数的重载方法,则不会发生这种情况:

    void x(int...x) {...}
    void x(int x) {...}
    

    然后编译器会选择第二种方法。

    【讨论】:

      【解决方案3】:

      因为这个类是由 Josh Bloch 设计的,而且那个人知道事情是如何运作的。 :) 除了创建数组外,varargs 方法还包含循环,这对 JIT 优化代码有更多的工作。

      例如,如果我们看一下带有五个参数的重载版本的实现:

      result.add(e1);
      result.add(e2);
      result.add(e3);
      result.add(e4);
      result.add(e5);
      

      我们注意到它是某种已经存在的unrolled loop,可能看起来像:

      for (E e : Arrays.asList(e1, e2, e3, e4, e5)) {
         result.add(e);
      }
      

      此外,更短更简单的方法比更长更复杂的方法更有可能被内联。

      【讨论】:

        【解决方案4】:

        来自javadoc

        此方法的重载用于初始化枚举集 一到五个元素。提供了第六次重载 使用可变参数功能。此重载可用于创建 一个枚举集,最初包含任意数量的元素,但是 可能比不使用可​​变参数的重载运行得更慢。

        【讨论】:

          猜你喜欢
          • 2011-04-13
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          • 2016-06-18
          • 1970-01-01
          • 1970-01-01
          • 2011-01-31
          相关资源
          最近更新 更多