Efficiency of Java “Double Brace Initialization”?

前端 未结 15 2114
清歌不尽
清歌不尽 2020-11-21 15:35

In Hidden Features of Java the top answer mentions Double Brace Initialization, with a very enticing syntax:

Set flavors = new HashSet         


        
相关标签:
15条回答
  • 2020-11-21 16:30

    I second Nat's answer, except I would use a loop instead of creating and immediately tossing the implicit List from asList(elements):

    static public Set<T> setOf(T ... elements) {
        Set set=new HashSet<T>(elements.size());
        for(T elm: elements) { set.add(elm); }
        return set;
        }
    
    0 讨论(0)
  • 2020-11-21 16:34

    Loading many classes can add some milliseconds to the start. If the startup isn't so critical and you are look at the efficiency of classes after startup there is no difference.

    package vanilla.java.perfeg.doublebracket;
    
    import java.util.*;
    
    /**
     * @author plawrey
     */
    public class DoubleBracketMain {
        public static void main(String... args) {
            final List<String> list1 = new ArrayList<String>() {
                {
                    add("Hello");
                    add("World");
                    add("!!!");
                }
            };
            List<String> list2 = new ArrayList<String>(list1);
            Set<String> set1 = new LinkedHashSet<String>() {
                {
                    addAll(list1);
                }
            };
            Set<String> set2 = new LinkedHashSet<String>();
            set2.addAll(list1);
            Map<Integer, String> map1 = new LinkedHashMap<Integer, String>() {
                {
                    put(1, "one");
                    put(2, "two");
                    put(3, "three");
                }
            };
            Map<Integer, String> map2 = new LinkedHashMap<Integer, String>();
            map2.putAll(map1);
    
            for (int i = 0; i < 10; i++) {
                long dbTimes = timeComparison(list1, list1)
                        + timeComparison(set1, set1)
                        + timeComparison(map1.keySet(), map1.keySet())
                        + timeComparison(map1.values(), map1.values());
                long times = timeComparison(list2, list2)
                        + timeComparison(set2, set2)
                        + timeComparison(map2.keySet(), map2.keySet())
                        + timeComparison(map2.values(), map2.values());
                if (i > 0)
                    System.out.printf("double braced collections took %,d ns and plain collections took %,d ns%n", dbTimes, times);
            }
        }
    
        public static long timeComparison(Collection a, Collection b) {
            long start = System.nanoTime();
            int runs = 10000000;
            for (int i = 0; i < runs; i++)
                compareCollections(a, b);
            long rate = (System.nanoTime() - start) / runs;
            return rate;
        }
    
        public static void compareCollections(Collection a, Collection b) {
            if (!a.equals(b) && a.hashCode() != b.hashCode() && !a.toString().equals(b.toString()))
                throw new AssertionError();
        }
    }
    

    prints

    double braced collections took 36 ns and plain collections took 36 ns
    double braced collections took 34 ns and plain collections took 36 ns
    double braced collections took 36 ns and plain collections took 36 ns
    double braced collections took 36 ns and plain collections took 36 ns
    double braced collections took 36 ns and plain collections took 36 ns
    double braced collections took 36 ns and plain collections took 36 ns
    double braced collections took 36 ns and plain collections took 36 ns
    double braced collections took 36 ns and plain collections took 36 ns
    double braced collections took 36 ns and plain collections took 36 ns
    
    0 讨论(0)
  • 2020-11-21 16:34

    While this syntax can be convenient, it also adds a lot of this$0 references as these become nested and it can be difficult to step debug into the initializers unless breakpoints are set on each one. For that reason, I only recommend using this for banal setters, especially set to constants, and places where anonymous subclasses don't matter (like no serialization involved).

    0 讨论(0)
提交回复
热议问题