Java Object in list doesn’t get found



I have a problem. I have the following class:

public class Cross implements Comparable<Cross> {
    
    private Long openTime;
    private String market;
    private String coin;
    private String period;
    private String metric1;
    private String metric2;
    private Double close;
    private String trend;


    public Long getOpenTime() {
        return this.openTime;
    }

    public void setOpenTime(long openTime) {
        this.openTime = openTime;
    }

    public String getMarket() {
        return this.market;
    }

    public void setMarket(String market) {
        this.market = market;
    }

    public String getCoin() {
        return this.coin;
    }

    public void setCoin(String coin) {
        this.coin = coin;
    }

    public String getPeriod() {
        return this.period;
    }

    public void setPeriod(String period) {
        this.period = period;
    }

    public String getMetric1() {
        return this.metric1;
    }

    public void setMetric1(String metric1) {
        this.metric1 = metric1;
    }

    public String getMetric2() {
        return this.metric2;
    }

    public void setMetric2(String metric2) {
        this.metric2 = metric2;
    }

    public Double getClose() {
        return this.close;
    }

    public void setClose(double close) {
        this.close = close;
    }

    public String getTrend() {
        return this.trend;
    }


    @Override
    public boolean equals(Object object) {

        if (object != null && object instanceof Cross) {
            Cross cross = (Cross) object;
            return (
                openTime.equals(cross.getOpenTime()) &&
                market.equals(cross.getMarket()) &&
                coin.equals(cross.getCoin()) &&
                period.equals(cross.getPeriod()) &&
                metric1.equals(cross.getMetric1()) &&
                metric2.equals(cross.getMetric2())
            );
        }

        return false;
    }


    @Override
    public int compareTo(Cross o) {
        return this.getOpenTime().compareTo(o.getOpenTime());
    }

}

Now I have a list containing 500 objects of these elements. Here are the first 4 shown:

{ openTime='1504332000000', market='USDT', coin='ETH', period='2h', metric1='EMA12', metric2='EMA26', close='363.7', trend='Down'}
{ openTime='1504663200000', market='USDT', coin='ETH', period='2h', metric1='EMA12', metric2='EMA26', close='325.73', trend='Up'}
{ openTime='1504879200000', market='USDT', coin='ETH', period='2h', metric1='EMA12', metric2='EMA26', close='294.05', trend='Down'}
{ openTime='1505181600000', market='USDT', coin='ETH', period='2h', metric1='EMA12', metric2='EMA26', close='304.41', trend='Up'}

In a variable I have stored the epoch of a specific datetime and with that I want to find the first valid cross, so I tried this:

private Cross getValidCross(List<Cross> crossList, LocalDateTime runDateTimeGMT0) {
    long searchEpoch = runDateTimeGMT0.toEpochSecond(ZoneOffset.UTC) * 1000;
    return crossList.stream().filter(cross -> cross.getOpenTime() < searchEpoch).max(Cross::compareTo).orElse(null);
}

But this code returns the value null When my searchEpoch is for example: 1514764800000. In the list I do see multiple objects that have a lower openTime than the searchEpoch. The result I want is the cross with the highest openTime, but it still has to be smaller than the searchEpoch.

Here is the error I get:

runDateTimeGMT0: 2018-01-01T00:00
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at com.hatop.drivers.SimulatorDriver.run(SimulatorDriver.java:297)
        at com.hatop.drivers.HatopDriver.main(HatopDriver.java:120)
Caused by: java.lang.NullPointerException: Cannot invoke "com.hatop.models.Cross.getTrend()" because the return value of "com.hatop.drivers.HatopDriver.getValidCross(List<Cross>, LocalDateTime)" 
is null
        at com.hatop.strategies.modules.module_java001.run(module_java001.java:186)
        ... 6 more

Why is my return value null?

Answer

This is caused due to the value the argument runDateTimeGMT0 is given and this:

long searchEpoch = runDateTimeGMT0.toEpochSecond(ZoneOffset.UTC) * 1000;

Since this is working:

public class Demo {
    private static Cross getValidCross(List<Cross> crossList, LocalDateTime runDateTimeGMT0) {
        long searchEpoch = 1514764800000L;

        return crossList.stream()
                .filter(cross -> cross.getOpenTime() < searchEpoch)
                .max(Cross::compareTo)
                .orElse(null);
    }

    @SneakyThrows
    public static void main(String[] args) {
        List<Cross> crosses = Arrays.asList(
                new Cross(1504332000000L, "USDT", "ETH", "2h", "EMA12", "EMA26", 363.7, "Down"),
                new Cross(1504663200000L, "USDT", "ETH", "2h", "EMA12", "EMA26", 325.73, "Up"),
                new Cross(1504879200000L, "USDT", "ETH", "2h", "EMA12", "EMA26", 294.05, "Down"),
                new Cross(1505181600000L, "USDT", "ETH", "2h", "EMA12", "EMA26", 304.41, "Up")
        );

        Cross validCross = getValidCross(crosses, null);

        System.out.println(validCross);
    }
}

Output:

Cross(openTime=1505181600000, market=USDT, coin=ETH, period=2h, metric1=EMA12, metric2=EMA26, close=304.41, trend=Up)

By the way, equals() is implemented without hashcode() – a recipe for problems.



Source: stackoverflow