首頁>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个元素.

最新回復
  • 5月前
    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");
    

  • 5月前
    2 #

    您怀疑,這是一項效能增強. Vararg方法"在幕後"建立一个陣列,並且拥有直接采用1-10个引數的方法可以避免這種多餘的陣列建立。

  • 5月前
    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所有者自己在另一个答案的註釋中確认了)。

  • 5月前
    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:連線圖標题中的字元串和表達式