Java 8 : functional way to write sort, filter and count at same time

dipamchang :

I am pretty new to Java, and I am trying to write the below logic in functional way.

I have a list of Objects, which have many fields. List<someObject> The fields of interest for now are long timestamp and String bookType

The problem statement is - I want to find the count of number of Objects in given list which have the same bookType as the one with lowest timestamp.

For example, if we sort the given list of objects based on timestamp in ascending order, and the first object in the sorted list has bookType field as SOMETYPE ; then I want to find out how many Objects are there in the list with the bookType SOMETYPE

I have written this logic using the plain old non functional way, by maintaing 2 temp variables and then iterating over the list once to find the lowest timestamp and the corresponding bookType amd a count of each bookType

But this is not acceptable to be run in a lambda, as it requires variables to be final

I could only write the part where I could sort the given list based on timestamp

n.stream().sorted(Comparator.comparingLong(someObject::timestamp)).collect(Collectors.toList());

I am stuck how to proceed with finding the count of the lowest timestamp bookType

m.antkowicz :

But this is not acceptable to be run in a lambda, as it requires variables to be final

First of all - this is not a problem since you can make your variable Effectively final by creating eg. single entry array and pass its single (first) object to the lambda

Second thing is that there's basically no sense to put everything in one lambda - think about this, how logically finding min value is connected with counting objects grouped by some attribute? It is not - putting this (somehow) to one stream will just obfuscate your code

What you should do - you should prepare method to find min value and returning you it's bookType then stream collection and group it by bookType and return size of the collection with given key value

It could look like on this scratch:

public class Item {
    private final long timestamp;
    private final String bookType;

    // Constructors, getters etc
}

// ...

public int getSizeOfBookTypeByMinTimestamp() {
    return items.stream()
        .collect(Collectors.groupingBy(Item::getBookType))
        .get(getMin(items))
        .size();
}

private String getMin(List<Item> items) {
    return items
        .stream()
        .min(Comparator.comparingLong(Item::getTimestamp))
        .orElse( /* HANDLE NO OBJECT */ ) // you can use also orElseThrow etc
        .getBookType();
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=124872&siteId=1