2014-02-20 15 views
9

Ich habe Guava ImmutableMap mit einer Builder für eine Weile verwendet, ohne viel darüber nachzudenken, wie/warum es funktioniert. Ich habe in der Art und Weise der Builder wurde unter Verwendung der Javadoc beschrieben:Guava ImmutableMap Builder Syntax

ImmutableMap<String, Integer> WORD_TO_INT = 
      new ImmutableMap.Builder<String, Integer>() 
       .put("one", 1) 
       .put("two", 2) 
       .put("three", 3) 
       .build(); 

Ich habe auch Beispiele gesehen elsewhere auf SO dieser Syntax:

ImmutableMap<String,Integer> myMap = ImmutableMap.<String, Integer>builder() 
    .put("one", 1) 
    .put("two", 2) 
    .put("three", 3) 
    .build(); 

Beide scheinen genau das gleiche Ergebnis zu erzielen .

Ein kurzer Blick auf die ImmutableMapsource zeigt, dass der statische builder() Aufruf im zweiten Beispiel gibt: new Builder<K, V>()

Es gibt keinen funktionalen Unterschied zwischen den beiden Methoden zu sein scheint.

Gibt es einen Unterschied unter der Haube? Irgendein Grund, das eine oder das andere zu bevorzugen?

EDIT: Hinzufügen von Bytecode-Differenz.

Die erzeugte Bytecode fast identisch, außer für eine Zeile:

Methode 1 (Builder<K,V>):

static {}; 
    0 new com.google.common.collect.ImmutableMap$Builder [12] 
    3 dup 
    4 invokespecial com.google.common.collect.ImmutableMap$Builder() [14] 
    7 ldc <String "key1"> [17] 
    ........ 

Methode 2 :(<K,V>builder())

static {}; 
    0 invokestatic com.google.common.collect.ImmutableMap.builder() : com.google.common.collect.ImmutableMap$Builder [12] 
    3 ldc <String "key1"> [18] 
    ........ 

Danach sie sind so ziemlich das Gleiche, die erste Zeile ist anders, macht angesichts der Unterschiede der Quellen Sinn, aber ich bin mir nicht sicher, warum die erste Zeileaufruft 210 und das zweite nicht.

Antwort

9

Nein, sie sind identisch. Der Grund für die erste Syntax ist, dass es ein schöner Einzeiler ist.

Der Grund für die zweite Syntax ist, dass Sie möglicherweise eine Schleife oder andere Flusskontrolle haben, müssen Sie möglicherweise die Builder umgehen.

Zum Beispiel:

public static void main(final String[] args) throws Exception { 
    final ImmutableList.Builder<Integer> lb = ImmutableList.builder(); 
    for (final String arg : args) { 
     lb.add(Integer.parseInt(arg)); 
    } 
} 

Und bevor Sie es sagen, ja ein FluentIterable würde wahrscheinlich in diesem Fall besser sein - aber es ist nur ein Beispiel.

+0

Irgendeine Idee, warum der 'dup' im Bytecode für den ersten auftaucht? Ich weiß nicht genug über Bytecode, um zu wissen, ob das typisch ist oder nicht. – Durandal

+0

@MagicMan Wenn Sie sich den Quellcode ansehen, werden Sie sehen, dass die Methoden unterschiedlich sind - ich bin nicht überrascht, dass der Bytecode anders ist. Warum es den Wert verdoppelt, bin ich nicht sicher. –

+0

Ahh, solange es keinen großen Unterschied gibt, mache ich mir keine Sorgen. Beispiel macht deutlich, wie ich es benutzen sollte, danke! – Durandal

0

Wie in javadoc angegeben, entspricht der generierte Builder dem Builder, der vom UnmutableMap.Builder-Konstruktor erstellt wird.

Es empfiehlt sich, eine solche Methode zu schreiben, wenn Sie das Builder-Muster anwenden. Dies bietet eine fließende Möglichkeit, es zu verwenden und kann als "syntaktischer Zucker" betrachtet werden.