首页>Program>source

Java 9随附了便捷工厂方法,用于创建不可变列表.最后,列表创建非常简单:

List<String> list = List.of("foo", "bar");

但是此方法有12种重载版本,其中11种包含0到10个元素,而1种包含var args。

static <E> List<E>  of(E... elements)

Set也是如此 和 Map

既然有var args方法,那么拥有额外的11种方法有什么意义?

我认为是var-args创建一个数组,因此其他11种方法可以跳过创建额外对象的过程,并且在大多数情况下,可以使用0-10个元素.

最新回答
  • 2021-1-11
    1 #

    来自JEP文档本身-

    Description -

    These will include varargs overloads, so that there is no fixed limit on the collection size. However, the collection instances so created may be tuned for smaller sizes. Special-case APIs (fixed-argument overloads) for up to ten of elements will be provided. While this introduces some clutter in the API, it avoids array allocation, initialization, and garbage collection overhead that is incurred by varargs calls. 重要的是,无论是否调用了fixed-arg或varargs重载,调用站点的源代码都是相同的。


    编辑-要添加动机,也正如@CKing在评论中所提到的:

    Non-Goals -

    It is not a goal to support high-performance, scalable collections with arbitrary numbers of elements. The focus is on small collections

    Motivation -

    创建一个小的,不可修改的集合(例如,一个集合)包括构造它,将其存储在局部变量中,并对其多次调用add(),然后将其包装。

    Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));
    

    通过结合流工厂方法和收集器,可以使用Java 8 Stream API来构造小的收集器。

    // Java 8
    Set<String> set1 = Collections.unmodifiableSet(Stream.of("a", "b", "c").collect(Collectors.toSet()));
    

    通过提供用于创建小型集合实例的库API可以获得集合文字的大部分好处,与更改语言相比,这大大降低了成本和风险.例如,创建一个小的Set实例的代码可能如下所示:

    // Java 9 
    Set set2 = Set.of("a", "b", "c");
    

  • 2021-1-11
    2 #

    您怀疑,这是一项性能增强. Vararg方法"在幕后"创建一个数组,并且拥有直接采用1-10个参数的方法可以避免这种多余的数组创建。

  • 2021-1-11
    3 #

    您可能会发现Josh Bloch的项目42的以下段落 有效的Java(第二版):

    Every invocation of a varargs method causes an array allocation and initialization. If you have determined empirically that you can’t afford this cost but you need the flexibility of varargs, there is a pattern that lets you have your cake and eat it too. Suppose you’ve determined that 95 percent of the calls to a method have three or fewer parameters. Then declare five overloadings of the method, one each with zero through three ordinary parameters, and a single varargs method for use when the number of arguments exceeds three [...]

    p

    您也可以反过来查看它.由于varargs方法可以接受数组,因此该方法可以用作将数组转换为 List的替代方法。

    String []strArr = new String[]{"1","2"};
    List<String> list = List.of(strArr);
    

    此方法的替代方法是使用 Arrays.asList 但对 List所做的任何更改 在这种情况下将反映在数组中,而 List.of则不然 .因此,您可以使用 List.of 当你不想要 List时 和要同步的阵列。

    Note 规范中给出的理由对我来说似乎是微优化. (这已经由API所有者自己在另一个答案的注释中确认了)。

  • 2021-1-11
    4 #

    此模式用于优化接受varargs参数的方法.

    如果您能确定大多数时间只使用其中的几个,则您可能想定义一个方法重载,其中包含最常用的参数:

    public void foo(int num1);
    public void foo(int num1, int num2);
    public void foo(int num1, int num2, int num3);
    public void foo(int... nums);
    

    这将帮助您避免在调用varargs方法时创建数组.用于性能优化的模式:

    List<String> list = List.of("foo", "bar");
    // Delegates call here
    static <E> List<E> of(E e1, E e2) { 
        return new ImmutableCollections.List2<>(e1, e2); // Constructor with 2 parameters, varargs avoided!
    }
    

    更有趣的是,从3个参数开始,我们再次委托给varargs构造函数:

    static <E> List<E> of(E e1, E e2, E e3) { 
        return new ImmutableCollections.ListN<>(e1, e2, e3); // varargs constructor
    }
    

    目前看来这很奇怪,但是正如我可能猜到的-这是为将来的改进保留的,并且作为一种选择,所有构造函数的潜在重载 List3(3 params), List7(7 params)...

  • javascript:命中测试的SVG形状?
  • r:连接图标题中的字符串和表达式