我不精通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;
}
}我知道我可以在这里使用枚举,但即使这样,我也可能会遇到同样的问题。每次我调用getSortedFruitSet时,它可能会创建新的TreeSet并填充它,这似乎是不必要的。我可以创建这个TreeSet的另一个静态实例,但是有没有其他方法来优化它呢?编译器或运行时是否对这种静态方法进行了优化?优化这样的方法调用有意义吗?
发布于 2016-08-10 17:09:03
java编译器不做这样的优化。
当我们用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因此,正如您所看到的,始终有一个new和invokespecial与TreeSet关联。(这将创建一个新的TreeSet对象,当您查看字节码时,创建过程分为两个步骤。一个步骤new和一个调用构造函数的invokespecial。
JIT编译器(可能)可以做到这一点
JIT可以在这里进行优化,但它对频繁执行的方法进行优化。要测试这一点,您需要多次调用该方法,并查看JIT生成的汇编代码。我现在不能验证这一点,,但可能会返回到答案,所以稍后-如果在此期间没有其他人这样做的话。
很抱歉只回答了你问题的一部分。顺便说一句,Java编译器(从java到字节码)通常只做很少的优化:-)
https://stackoverflow.com/questions/38868669
复制相似问题