我对java编译器并不精明,但想知道java是否进行了这样的优化。问题在于:
class A {
private final static Map<String, String> fruitIds = new HashMap<String, String>();
static {
fruitIds.put("Orange", "1");
fruitIds.put("Apple", "2");
fruitIds.put("banana", "4");
}
public static Set<Integer> getSortedFruitSet() {
Iterator<String> iterator = fruitIds.values().iterator();
Set<Integer> returnSet = new TreeSet<Integer>();
while (iterator.hasNext()) {
returnSet.add(Integer.valueOf(iterator.next()));
}
return returnSet;
}
}
我知道我可以在这里使用Enums,但即便如此,我可能会遇到同样的问题。每当我调用getSortedFruitSet
时,它可能会创建新的TreeSet并填充它,这似乎是不必要的。我可以创建这个TreeSet的另一个静态实例,但有另一种方法来优化它吗?编译器或运行时是否对这种静态方法进行了任何优化?优化此类方法调用甚至是否有意义?
答案 0 :(得分:0)
当我们用javap -c
查看你的getSortedFruitSet()方法时,我们可以看到这段代码的编译版本。
public static java.util.Set<java.lang.Integer> getSortedFruitSet();
descriptor: ()Ljava/util/Set;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=0
0: getstatic #2 // Field fruitIds:Ljava/util/Map;
3: invokeinterface #3, 1 // InterfaceMethod java/util/Map.values:()Ljava/util/Collection;
8: invokeinterface #4, 1 // InterfaceMethod java/util/Collection.iterator:()Ljava/util/Iterator;
13: astore_0
14: new #5 // class java/util/TreeSet
17: dup
18: invokespecial #6 // Method java/util/TreeSet."<init>":()V
21: astore_1
22: aload_0
23: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
28: ifeq 53
31: aload_1
32: aload_0
33: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
38: checkcast #9 // class java/lang/String
41: invokestatic #10 // Method java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
44: invokeinterface #11, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
49: pop
50: goto 22
53: aload_1
54: areturn
LineNumberTable:
line 13: 0
line 14: 14
line 15: 22
line 16: 31
line 18: 53
StackMapTable: number_of_entries = 2
frame_type = 253 /* append */
offset_delta = 22
locals = [ class java/util/Iterator, class java/util/Set ]
frame_type = 30 /* same */
Signature: #36
您可以看到,TreeSet始终存在new
和invokespecial
。 (这将创建一个新的TreeSet对象,当您查看字节码时,创建将变为两个步骤。一步new
和一个invokespecial
调用构造函数。
JIT可以在这里进行优化,但它会在经常执行的方法上执行此操作。要对此进行测试,您需要多次调用该方法并查看JIT生成的汇编代码。 我现在无法验证,但可能会回到答案,所以稍后 - 如果没有其他人同时这样做的话。
很抱歉只回答部分问题。 Java编译器(从java到字节码)一般只做很少的优化:-)