1

How can I use java streams to filter an object by the same porperty?

The HashSet tasks contains:

task=1, name=hello
task=2, name=hello

(I dont want to use equals/hashcode on "name")

Now I want to filter the tasks producing a new HashSet with unique name-property.

All objects having the same name should be treated as equal:

tasks.stream.filter(???);

I can solve that by creating a new list and with 2 for-loops by indexing next element and looking for the name if it was already put into the list. However, maybe there is an one liner for such problems? Maybe with stream.filter()?

Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
nimo23
  • 5,170
  • 10
  • 46
  • 75

2 Answers2

2

You may first create a map using the task name as the key and the relevant Task as the value. Ignore the duplicate Tasks merely by using a mergeFunction. Then get all the distinct tasks as a Set view.

Set<Task> distinctTasks = tasks.stream().collect(Collectors.collectingAndThen(
    Collectors.toMap(Task::getName, Function.identity(), 
        (a, b) -> a), m -> new HashSet<>(m.values())));
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
0

I find one solutions:

List<Task> tasksDistinct = tasks.stream()
                    .collect(Collectors.groupingBy(Task::getName))
                    .values()
                    .stream()
                    .flatMap(m -> m.stream())
                    .collect(Collectors.toList());

Are there any better solutions?

nimo23
  • 5,170
  • 10
  • 46
  • 75
  • 1
    where and what are you `filter`ing? – Naman Aug 22 '19 at 06:09
  • It is a indirect filtering by "Task::getName" and knowing that map key is unique. Do you know a solution with explicit `stream.filter()`? – nimo23 Aug 22 '19 at 06:11
  • But if you don't use that `Map` anymore, what are you achieving by `groupingBy`? You eventually have a list of all `Task`s, ordered possibly by the keys(`name`) iterated for the map. – Naman Aug 22 '19 at 06:13
  • `groupingBy` constructs the map with unique key. The origin task is a HashSet with duplicate names.. – nimo23 Aug 22 '19 at 06:15
  • Yes, `groupingBy` constructs the map with unique keys and *lists of all elements* as values. Your subsequent operation joins all of them back to a list containing all elements. You could avoid this by replacing `.flatMap(m -> m.stream())` with `.map(m -> m.get(0))`, to only use the first occurrence for every group, instead of all of them. But that’s less efficient than [the accepted answer](https://stackoverflow.com/a/57602947/2711488) which doesn’t keep the other occurrences in the first place. – Holger Aug 22 '19 at 09:44