Skip to content

Instantly share code, notes, and snippets.

@yradtsevich
Last active May 6, 2017 16:30
Show Gist options
  • Save yradtsevich/991ca6896998c371b4d5b7ca20144d25 to your computer and use it in GitHub Desktop.
Save yradtsevich/991ca6896998c371b4d5b7ca20144d25 to your computer and use it in GitHub Desktop.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Supplier;
/*
================= RESULTS =================
=============================
NpeCatchDeepGetter:
dt = 200, c = 8190023
dt = 170, c = 8190023
dt = 153, c = 8190023
dt = 149, c = 8190023
dt = 143, c = 8190023
dt = 131, c = 8190023
dt = 152, c = 8190023
dt = 147, c = 8190023
dt = 144, c = 8190023
dt = 139, c = 8190023
Call statistics (except the first 5 calls): LongSummaryStatistics{count=5, sum=713, min=131, average=142.600000, max=152}
=============================
IfDeepGetter:
dt = 180, c = 8190023
dt = 142, c = 8190023
dt = 136, c = 8190023
dt = 133, c = 8190023
dt = 162, c = 8190023
dt = 149, c = 8190023
dt = 150, c = 8190023
dt = 148, c = 8190023
dt = 147, c = 8190023
dt = 145, c = 8190023
Call statistics (except the first 5 calls): LongSummaryStatistics{count=5, sum=739, min=145, average=147.800000, max=150}
=============================
LambdaElvisDeepGetter:
dt = 969, c = 8190023
dt = 611, c = 8190023
dt = 644, c = 8190023
dt = 604, c = 8190023
dt = 732, c = 8190023
dt = 659, c = 8190023
dt = 669, c = 8190023
dt = 370, c = 8190023
dt = 620, c = 8190023
dt = 367, c = 8190023
Call statistics (except the first 5 calls): LongSummaryStatistics{count=5, sum=2685, min=367, average=537.000000, max=669}
=============================
TernaryDeepGetter:
dt = 237, c = 8190023
dt = 239, c = 8190023
dt = 171, c = 8190023
dt = 177, c = 8190023
dt = 191, c = 8190023
dt = 174, c = 8190023
dt = 190, c = 8190023
dt = 198, c = 8190023
dt = 172, c = 8190023
dt = 168, c = 8190023
Call statistics (except the first 5 calls): LongSummaryStatistics{count=5, sum=902, min=168, average=180.400000, max=198}
=============================
LambdaNpeCatchDeepGetter:
dt = 262, c = 8190023
dt = 199, c = 8190023
dt = 211, c = 8190023
dt = 199, c = 8190023
dt = 208, c = 8190023
dt = 192, c = 8190023
dt = 196, c = 8190023
dt = 209, c = 8190023
dt = 227, c = 8190023
dt = 237, c = 8190023
Call statistics (except the first 5 calls): LongSummaryStatistics{count=5, sum=1061, min=192, average=212.200000, max=237}
*/
/** @author Yahor Radtsevich */
public class Elvis {
private static final int N = 10_000_000;
public static void main(String[] args) {
A[] a = new A[N];
Arrays.setAll(a, index -> randomA());
for (DeepGetter deepGetter : new DeepGetter[]{new NpeCatchDeepGetter(), new IfDeepGetter(), new LambdaElvisDeepGetter(), new TernaryDeepGetter(), new LambdaNpeCatchDeepGetter()}) {
List<Long> dtList = new ArrayList<>();
System.out.println("=============================\n"
+ deepGetter.getClass().getSimpleName() + ":");
for (int i = 0; i < 10; i++) {
long t0 = System.currentTimeMillis();
int c = 0;
for (int j = 0; j < N; j++) {
c += deepGetter.getLength(a[j]);
}
long dt = System.currentTimeMillis() - t0;
dtList.add(dt);
System.out.println("dt = " + dt + ", c = " + c);
}
System.out.println("Call statistics (except the first 5 calls): " + dtList.stream().skip(5).mapToLong(x -> x).summaryStatistics());
}
}
private interface DeepGetter {
int getLength(A a);
}
private static class LambdaElvisDeepGetter implements DeepGetter {
public int getLength(A a) {
return Optional.ofNullable(a)
.map(A::getB)
.map(B::getC)
.map(C::getS)
.map(String::length)
.orElse(0);
}
}
private static class TernaryDeepGetter implements DeepGetter {
public int getLength(A a) {
return a == null ? 0
: a.getB() == null ? 0
: a.getB().getC() == null ? 0
: a.getB().getC().getS() == null ? 0
: a.getB().getC().getS().length();
}
}
private static class IfDeepGetter implements DeepGetter {
public int getLength(A a) {
if (a != null) {
B b = a.getB();
if (b != null) {
C cc = b.getC();
if (cc != null) {
String s = cc.getS();
if (s != null) {
return s.length();
}
}
}
}
return 0;
}
}
private static class NpeCatchDeepGetter implements DeepGetter {
public int getLength(A a) {
try {
return a.getB().getC().getS().length();
} catch (NullPointerException e) {
return 0;
}
}
}
private static class LambdaNpeCatchDeepGetter implements DeepGetter {
public int getLength(A a) {
return NpeSafeLambda.get(() -> a.getB().getC().getS().length());
}
}
static class NpeSafeLambda {
static Integer get(Supplier<Integer> f) {
try {
return f.get();
} catch (NullPointerException e) {
return 0;
}
}
}
private static Random random = new Random(1);
private static A randomA() {
int rand = random.nextInt();
A a = null;
if ((rand & 0xF) != 0) { // probability = 15/16 = 0.9375
a = new A();
if ((rand & (0x7 << 4)) != 0) { // probability = 7/8 * 15/16 = 0.8203125
B b = new B();
a.setB(b);
if ((rand & (0x3 << 7)) != 0) { // probability = 3/4 * 7/8 * 15/16 = 0.615234375
C c = new C();
b.setC(c);
if ((rand & (0x1 << 9)) != 0) { // probability = 1/2 * 3/4 * 7/8 * 15/16 = 0.3076171875
StringBuilder sBuilder = new StringBuilder(10);
for (int i = 0; i < random.nextInt(10); i++) {
sBuilder.append((char) (random.nextInt('Z' - 'A' + 1) + 'A'));
}
c.setS(sBuilder.toString());
}
}
}
}
return a;
}
private static class A {
B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
private static class B {
C c;
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
}
private static class C {
String s;
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment