Search code examples
javaarraysdictionarynullpointerexceptionjava-stream

How to convert Array of Map<String, Object> to Map<Long, Long> using streams


public class Sample {

    Map<Long, Long> count(Map<String, UserStats> visits[]) {

        Map<Long, Long> visitsNum = new HashMap<>();
        Arrays.stream(visits).map(m -> {

            Map<Long, Long> visitsList = new HashMap<>();
            m.forEach((k, v) -> {
                String microSerNum = k;
                UserStats user = v;
                Long count1 = 0L;
                Long longMicroSerNum =0L;
                try {
                    longMicroSerNum = Long.parseLong(microSerNum);
                } catch (Exception e) {

                    System.out.println("Microserive number is not a Long data type");
                    return;
                }
                if (user == null)
                {
                    System.out.println("User not visited the Microservice " + longMicroSerNum);
                    return;
                }
                else {
                    Optional<Long> count = user.VisitCounter;

                    if (count.isPresent())

                    count1 = count.get();

                    System.out.println("Number of times user vistied the Microservice " +longMicroSerNum + " is "+ count1);

                }

                visitsList.put(longMicroSerNum, count1);

            });
            
            return visitsList;

        }).//collect(Collectors.toMap(e->e.getKey, e->e.getValue));
        
        forEach((e) -> {
            System.out.println(e);
        });


        return visitsNum; // should return a map
    }

    record UserStats(Optional<Long> VisitCounter) {

    }

    public static void main(String ar[]) {
        Sample a = new Sample();
        UserStats u = new UserStats(Optional.of(10L));
        UserStats u1 = new UserStats(Optional.of(20L));

        Map<String, UserStats> m1[] = new HashMap[10];

        Map<String, UserStats> m2 = new HashMap<>();

        Map<String, UserStats> m3 = new HashMap<>();
        m2.put("20", u);
        m2.put("30", u1);
        m3.put("", u);
        m3.put("50", null);

        m1[0] = m2;
        m1[1] = m3;

        Map<Long, Long> visitsNum = a.count(m1); //should catch the returned map
        
    }

}

Have to parse the String, Object's Optional values to Long types then discard the empty object or empty string values.

Getting below console output:

Number of times user vistied the Microservice 30 is 20
Number of times user vistied the Microservice 20 is 10
{20=10, 30=20}
Microserive number is not a Long data type
User not visited the Microservice 50
{}
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.Map.forEach(java.util.function.BiConsumer)" because "m" is null
    at CodingPractice.Sample.lambda$0(Sample.java:12)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at CodingPractice.Sample.count(Sample.java:48)
    at CodingPractice.Sample.main(Sample.java:78)

Solution

  • Map<String, UserStats> m1[] = new HashMap[10];
    

    and further:

    m1[0] = m2;
    m1[1] = m3;
    

    Only two elements are in your array of length 10, others are then set to null. Then, what do you think it will happen in count() at the call m.forEach if m is null?

    Change Map<String, UserStats> m1[] = new HashMap[10]; to Map<String, UserStats> m1[] = new HashMap[2];

    Aside: you are creating a generic array but that is bad (the compiler should have complain); your problem is mainly due to the fact that you used an array (fixed size and logical error then) where something like a list would have been much safer. Or at least filter the stream for non null elements...