Using try-catch over if conditions to safely set values with minimum performance impact in java
在这里,我的主要目标是安全地设置值,而不会产生性能(速度,内存,CPU等)影响。
我有一个愚蠢的选择(坏的风格)也在下面提到。
那么,最好的方法是什么? 选项1? 选项2? 还是另一个?
选项1 :
1 2 3 4 5 6 7 8 | if( animalData!=null && animalData.getBreedData()!=null && dogx.getBreed() != null && dogx.getBreed().getBreedCode() != null && animalData.getBreedData().get(dogx.getBreed().getBreedCode()) != null ){ dogx.getBreed().setBreedId(animalData.getBreedData().get(dogx.getBreed().getBreedCode())); } |
选项2:
1 | try{dogx.getBreed().setBreedId(animalData.getBreedData().get(dogx.getBreed().getBreedCode()));}catch(Exception e){} |
注意:这段代码是一个循环,有数千次迭代。
检查
您可以通过存储对
1 2 3 4 5 6 7 8 9 10 11 12 | BreedData breedData; DogBreed dogBreed; String breedCode; String breedId; if( animalData != null && (breedData = animalData.getBreedData())!=null && (dogBreed = dogx.getBreed()) != null && (breedCode = dogx.getBreed().getBreedCode()) != null && (breedId = breedData.get(breedCode)) != null ) { dogBreed.setBreedId(breedId); } |
选项3:
1 2 3 4 5 6 7 8 9 10 11 12 13 | Optional.ofNullable(animalData) .map(animalData -> animalData.getBreedData()) .ifPresent(breedData -> { Optional.ofNullable(dogx.getBreed()) .map(breed -> breed.getBreedCode()) .ifPresent(breedCode -> { thisBreedData = breedData.get(breedCode); // here we could use a third Optional call… if (thisBreedData != null) { dogx.getBreed().setBreedId(thisBreedData)); } }) }); } |
以上答案实际上没有回答你的问题。所以这是我的:
如果性能对您来说真的很重要 - 删除
1 2 3 4 5 6 7 8 | public boolean add(T element) { try { elementData[size++] = element; } catch (ArrayIndexOutOfBoundsException e) { ... } } |
添加了此try catch作为范围检查的替换。删除边界检查实际上使这个代码更快。
以下是证明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | @BenchmarkMode(Mode.Throughput) @Fork(1) @State(Scope.Thread) @Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000) @Measurement(iterations = 20, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000) public class BoundsCheck { @Param("1") int index; int[] ar; @Setup public void setup() { ar = new int[] {1, 2}; } @Benchmark public int boundCheck() { if (index >= ar.length) { throw new IndexOutOfBoundsException(); } return ar[index]; } @Benchmark public int noCheck() { return ar[index]; } @Benchmark public int noCheckWithTryCatch() { try { return ar[index]; } catch (RuntimeException e) { return -1; } } } |
结果:
1 2 3 4 | Benchmark (index) Mode Cnt Score Error Units BoundsCheck.boundCheck 1 thrpt 20 334197.761 ± 2593.034 ops/s BoundsCheck.noCheck 1 thrpt 20 370148.527 ± 9016.179 ops/s BoundsCheck.noCheckWithTryCatch 1 thrpt 20 371782.744 ± 17290.347 ops/s |
我们在这里能看到什么?消除边界检查可使您获得+ 10%的性能提升。
但是,这种方法仅适用于您可以保证数据中没有NPE的情况。因此异常实际上永远不会被抛出或抛出很少。否则,异常抛出可能会使您的代码更慢。
这里没有确切的答案。这实际上取决于您的数据,您需要知道您的数据才能得出任何进一步的结论。
另外,请记住,JIT可以在代码中尽可能地消除