Home > Blockchain >  Obtain from a List custom Objects of a List of distinct String values of Two String fields of these
Obtain from a List custom Objects of a List of distinct String values of Two String fields of these

Time:09-06

Java stream on specific fields in a custom class object

I have an ArrayList of Train objects.

Each Train has three fields: source, destination, cost.

I want to get all the place names, i.e. all distinct sources destinations.

I am using the below code, but as it can be observed, I'm using two streams to retrieve the data.

List<String> destinations = list.stream()
    .map(x -> x.getDestination())
    .distinct()
    .collect(Collectors.toList());

List<String> sources = List.stream()
    .map(x -> x.getSource())
    .distinct()
    .collect(Collectors.toList());

I was wondering how I could accomplish the same thing in a single stream? Can it be done using flatMap, or there's another way to achieve this?

List<String> allPlaces = ?

Also, is this possible to use Train class without getters?

CodePudding user response:

You had the right idea with flatMap - you can map a train to a stream that contains the source and destination, and then flatMap it to you "main" stream:

List<String> allPlaces =
    trains.stream()
          .flatMap(t -> Stream.of(t.getSource(), t.getDestination()))
          .distinct()
          .collect(Collectors.toList());

CodePudding user response:

In this case, we can utilize Java 16 method mapMulti(), which is functionally similar to flatMap(). It's meant for transforming a single stream element into a group of elements.

Here's how implementation might look like:

List<String> places = trains.stream()
    .<String>mapMulti((train, consumer) -> {
        consumer.accept(train.getSource());
        consumer.accept(train.getDestination());
    })
    .distinct()
    .toList();

Contrary to flatMap() it doesn't consume a stream, but operates via Consumer. mapMulti() a recommended alternative to flatMap() for situations when a new stream flatMap() requires would contain only a few elements (like in this case when we have only two elements: source and destination).

A quote from the API Note:

This method is preferable to flatMap in the following circumstances:

  • When replacing each stream element with a small (possibly zero) number of elements. Using this method avoids the overhead of creating a new Stream instance for every group of result elements, as required by flatMap. Also is this possible without the getters methods of class Train?

Sure, you can. But it's not a recommended practice to access instance fields directly. In Java we're using access modifier to hide and protect member-variables within the class, that's one of the aspects of Encapsulation.

  • Related