0

I have the following piece of code which groups the given entries (activities, which is Iterable<activity>) based on IDs.

For the final result, I want it to return a Map of ID to Iterables of the entries grouped by that ID.

For example: Map<String, Iterables<activity>>.

Right now, it returns a Map<String, List<activity>>.

        stream(activities)
            .collect(
                groupingBy(
                    activity -> {
                      if (activity.getID()) {
                        return activity.getID();
                      } else {
                        return activity.getName();
                      }
                    }));

I am unable to figure out a way to do this.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
NEz
  • 151
  • 1
  • 1
  • 13
  • You'll need to study up on the Java type system. A `List` _is_ an `Iterable`. `Iterable` is just an interface. It's implemented by many of the container types, providing a common way to iterate over all of them. For example, `for` loops accept any `Iterable` as source data. There's no concrete class called `Iterable`. – Gene Apr 20 '22 at 01:12

1 Answers1

0

There's no such notion in Java as truthy values, which exists in languages like javascript. I.e. String can't be resolved into boolean automatically (what your code attempts to do).

There are multiple ways of how you can check whether the given value is null and provide an alternative value.

If name attribute is guaranteed to be non-null you can use static method requireNonNullElse() of the Objects utility class:

.collect(Collectors.groupingBy(act -> Objects.requireNonNullElse(act.getID(), act.getName()));

If name attribute is nullable, then you have to provide a default value that will be used in case if both id and name equal to null. Because null key is not allowed with Collectors.groupingBy() and will result in NullPointerException at runtime.

For the case when both field could be null I suggest extracting the logic for obtaining the key into a separate method.

public static String getKey(Action action) {
    return action.getID() != null ? action.getID() :
         action.getName() != null ? action.getName() : "defaultKey";
}

Which can be used inside the collector like that:

.collect(Collectors.groupingBy(act -> getKey(act)); // or as a method reference MyClass::getKey

Sidenote: by convention, names of classes in Java should start with a capital letter: Student, Employee, Activity.

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