28

I am new to Java 8. I have a list of custom objects of type A, where A is like below:

 class A {
      int id;
      String name;
 }

I would like to determine if all the objects in that list have same name. I can do it by iterating over the list and capturing previous and current value of names. In that context, I found How to count number of custom objects in list which have same value for one of its attribute. But is there any better way to do the same in java 8 using stream?

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
Joy
  • 4,197
  • 14
  • 61
  • 131

5 Answers5

52

You can map from A --> String , apply the distinct intermediate operation, utilise limit(2) to enable optimisation where possible and then check if count is less than or equal to 1 in which case all objects have the same name and if not then they do not all have the same name.

boolean result = myList.stream()
                       .map(A::getName)
                       .distinct()
                       .limit(2)
                       .count() <= 1;

With the example shown above, we leverage the limit(2) operation so that we stop as soon as we find two distinct object names.

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
34

One way is to get the name of the first list and call allMatch and check against that.

String firstName = yourListOfAs.get(0).name;
boolean allSameName = yourListOfAs.stream().allMatch(x -> x.name.equals(firstName));
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 3
    The most efficient + clear solution using streams, IMO. The `allMatch` will short-circuit as soon as it finds a non-matching element. – Stephen C Dec 30 '17 at 07:18
  • 1
    If name can be null, add `if` statement to check `firstName` is not null and change to `allMatch(x -> firstName.equals(x.name));`. And if `firstName` is null still have to check all other names are null. It seems with Aomine's solution those cases are covered. – James Apr 11 '19 at 19:14
12

another way is to calculate count of distinct names using

boolean result = myList.stream().map(A::getName).distinct().count() == 1;

of course you need to add getter for 'name' field

Alex M981
  • 2,264
  • 14
  • 24
2

One more option by using Partitioning. Partitioning is a special kind of grouping, in which the resultant map contains at most two different groups – one for true and one for false.

by this, You can get number of matching and not matching

String firstName = yourListOfAs.get(0).name;

Map<Boolean, List<Employee>> partitioned =  employees.stream().collect(partitioningBy(e -> e.name==firstName));

Java 9 using takeWhile takewhile will take all the values until the predicate returns false. this is similar to break statement in while loop

String firstName = yourListOfAs.get(0).name;        

        List<Employee> filterList =  employees.stream()
                                               .takeWhile(e->firstName.equals(e.name)).collect(Collectors.toList());
        if(filterList.size()==list.size())
        {
            //all objects have same values 
        }
Niraj Sonawane
  • 10,225
  • 10
  • 75
  • 104
1

Or use groupingBy then check entrySet size.

boolean b  = list.stream()
             .collect(Collectors.groupingBy(A::getName, 
             Collectors.toList())).entrySet().size() == 1;
Hadi J
  • 16,989
  • 4
  • 36
  • 62