0

I have the following domain classes:

public class Task {
    private Project project;
}
public class Project{
    private int id;
}

And I have a list of tasks called tasks.

I would like to group Task objects by project's ids. The resulting type of the

I tried the code shown below. But it doesn't group objects by ids, but rather groups based on whether the key is the same object or not. I found duplicates, I tried to get rid of them, but I couldn't make it work.

tasks.stream().collect(Collectors.groupingBy(task::getProject));

I want something like that

tasks.stream().collect(Collectors.groupingBy(task::getProject::getId));

But unfortunately, I couldn't do that.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46

1 Answers1

1

As @n247s has pointed out in the comments, the syntax of the Method reference you're using is incorrect - you can't chain method reference (for more details, refer to the official tutorial).

The keyExtractor Function you need can be expressed only using a Lambda expression because in order to create a Method reference to an instance method of a Particular Object you need to have a reference to it, you don't have it (it's not possible in this case).

Here's the only option:

task -> task.getProject().getId()

It would be possible to create a Method reference of this type using a method of the nested object if you had a reference to the enclosing object stored somewhere. For instance, like that:

Task foo = new Task();
Function<Task, Integer> taskToId = foo.getProject()::getId;

But since you're dialing with a stream element, it not feasible.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • If i go this way it return map (project_id,task) but i want (project,task) how can i achieve that ? – Samet DAĞ Nov 14 '22 at 16:54
  • @SametDAĞ Then use `groupingBy(task::getProject)` like in your first code-snippet. It would give you a map `Map>`. If you need a map of type `Map` then you need to use a different collector - `toMap()`. – Alexander Ivanchenko Nov 14 '22 at 16:56
  • but it grouping by project objects . i want to group by project ids and package them as project – Samet DAĞ Nov 14 '22 at 16:57
  • @SametDAĞ `group by project ids and package them as project` - OK, `id` property is unique? If not, how to deal with duplicates? – Alexander Ivanchenko Nov 14 '22 at 16:59
  • yes ids are unique – Samet DAĞ Nov 14 '22 at 17:02
  • @SametDAĞ If `id` property is unique, then you need to [override `equals()` and `hashCode()` methods](https://stackoverflow.com/questions/2265503/why-do-i-need-to-override-the-equals-and-hashcode-methods-in-java) in the Project class based on it. And you'll be able to get the result you need with `groupingBy(task::getProject)`. Remember as a rule of thumb: always `equals/hashCode` of your custom objects that are interned to be used as a Key in a `HashMap`, or stored in a `HashSet`. – Alexander Ivanchenko Nov 14 '22 at 17:21
  • @SametDAĞ Since `id` is unique - the correct way to establish the identity of the `Project` instances is implement `equals/hashCode` based on it. – Alexander Ivanchenko Nov 14 '22 at 17:40