我们经常使用 Long.valueOf()进行同一场投射。这样就可以了,或者我们需要在其他字段中存储已转换的值然后使用。 例: 我们在String中收到特定的id,无论我们在哪里使用,我们每次都会使用Long.valueOf(id)。
喜欢:
void methodName(String id) {
//some code
... = Long.valueOf(id);
....
....
callOtherMethod(Long.valueOf(id));
....
...
map.put("urId", Long.valueOf(id));
....
}
当我们考虑性能和所有这些时,这是可以的。其他
这个很好去
喜欢:
void methodName(String id) {
//some code
Long longId = Long.valueOf(id);
... = longId;
....
....
callOtherMethod(longId);
....
...
map.put("urId", longId);
....
}
哪一个最好,为什么(如果你能解释)?
答案 0 :(得分:2)
我个人赞成不多次重复相同的操作。所以我更喜欢你的第二种方法。
编程时,多次写入的同一段代码往往是难闻的气味,如果你可以提取重复的代码片段以便重复使用,比如将重复的块提取到参数化方法,或者在这种情况下分配输出Long.valueOf(id)
对变量,您可以避免使用难以阅读的冗长代码。
答案 1 :(得分:0)
如果从Long.valueOf()
(或任何其他方法)返回的值应该多次使用,那么使用第二种方法总是更好。因为它的alsmot总是在本地存储它比再次计算它更便宜。
对于相关示例,使用JMH计算性能差异并不难。我创建了可以计算出来的小基准:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5)
@Measurement(iterations = 10)
@Fork(1)
@State(Scope.Thread)
public class ValueOfPerfTest {
@Param({ "1000" })
private String number;
@Param({ "10", "20", "30"})
private long tokens;
@Benchmark
public void cachedValueOf(Blackhole blackhole) {
Long l = Long.valueOf(number);
// three times using the consume
blackhole.consume(l);
blackhole.consume(l);
blackhole.consume(l);
Blackhole.consumeCPU(tokens);
}
@Benchmark
public void nonCachedValueOf(Blackhole blackhole) {
// three times using the consume
blackhole.consume(Long.valueOf(number));
blackhole.consume(Long.valueOf(number));
blackhole.consume(Long.valueOf(number));
Blackhole.consumeCPU(tokens);
}
@Benchmark
public Long valueOf(Blackhole blackhole) {
Blackhole.consumeCPU(tokens);
return Long.valueOf(number);
}
@Benchmark
public void baseline(){
Blackhole.consumeCPU(tokens);
}
}
我不想在这里找到JMH的具体内容,但主要区别在于nonCachedValueOf
调用Long.valueOf()
的3倍,相比之下,缓存版本只有一次。我的期望是非缓存版本会慢3倍,这基本上是结果显示:
[java] Benchmark (number) (tokens) Mode Samples Score Error Units
[java] i.n.a.p.ValueOfPerfTest.baseline 1000 10 avgt 10 11.238 ± 0.387 ns/op
[java] i.n.a.p.ValueOfPerfTest.baseline 1000 20 avgt 10 30.392 ± 0.668 ns/op
[java] i.n.a.p.ValueOfPerfTest.baseline 1000 30 avgt 10 50.217 ± 1.101 ns/op
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 1000 10 avgt 10 37.368 ± 2.035 ns/op
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 1000 20 avgt 10 54.614 ± 3.847 ns/op
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 1000 30 avgt 10 74.412 ± 2.474 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 1000 10 avgt 10 82.329 ± 2.649 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 1000 20 avgt 10 100.595 ± 2.476 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 1000 30 avgt 10 118.715 ± 3.277 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 1000 10 avgt 10 35.815 ± 0.766 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 1000 20 avgt 10 53.074 ± 3.942 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 1000 30 avgt 10 73.378 ± 2.318 ns/op
如果你深入研究结果,如果你排除基线(这里有30个代币),你会得到大约以下的结果:
[java] i.n.a.p.ValueOfPerfTest.cachedValueOf 24,195 ns/op
[java] i.n.a.p.ValueOfPerfTest.nonCachedValueOf 68,498 ns/op
[java] i.n.a.p.ValueOfPerfTest.valueOf 23,161 ns/op
相当清楚几乎因素3。
关于每次使用Long.valueOf创建任何新对象的问题?,如果数字不在缓存中,答案是肯定的.java有&#34的缓存;经常使用的值"默认情况下,这是从-128到127的数字。但是可以通过使用-XX:AutoBoxCacheMax
JVM选项来增加它。