0

How to get all elements with id = 2?

The below code is giving only the last one i.e. channelMetadataDetail3:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


public class APICheck {
    public static void main(String[] args) {

        List<ChannelMetadataDetails> channelMetadataDetails = 
        new ArrayList<ChannelMetadataDetails>();
        ChannelMetadataDetails channelMetadataDetail1 = 
        new ChannelMetadataDetails();
        channelMetadataDetail1.setId("2");
        channelMetadataDetail1.setUnitOfMeasureId("3");

        ChannelMetadataDetails channelMetadataDetail2 = 
        new ChannelMetadataDetails();
        channelMetadataDetail2.setId("2");
        channelMetadataDetail2.setUnitOfMeasureId("3");
        channelMetadataDetail2.setMeasureTypeId("5");

        ChannelMetadataDetails channelMetadataDetail3 = 
        new ChannelMetadataDetails();
        channelMetadataDetail3.setId("2");

        channelMetadataDetails.add(channelMetadataDetail1);
        channelMetadataDetails.add(channelMetadataDetail2);
        channelMetadataDetails.add(channelMetadataDetail3);

        channelMetadataDetails =channelMetadataDetails.
        stream().filter(cm -> cm.getId().equals("2")).
        filter(cm -> cm.getUnitOfMeasureId().equals(null)).
        filter(cm -> cm.getMeasureTypeId().equals(null)).
        collect(Collectors.toList());

    }   

}

NOTE:- If cm.getUnitOfMeasureId() is null then I will get NullPointerException

UPDATE:

In short, I only want those objects whose elements are non-null.

For example using for loop:

for (ChannelMetadataDetails cmEach : channelMetadataDetails) {
            if(cmEach.getId() != null && cmEach.getUnitOfMeasureId() == null && cmEach.getMeasureTypeId() == null) {
                channelMetadataDetails.stream().filter(cm -> cm.getId().equals("2")).collect(Collectors.toList());
            } else if(cmEach.getId() == null && cmEach.getUnitOfMeasureId() != null && cmEach.getMeasureTypeId() == null) {
                channelMetadataDetails.stream().filter(cm -> cm.getUnitOfMeasureId().equals("4")).collect(Collectors.toList());
            } else if(cmEach.getId() == null && cmEach.getUnitOfMeasureId() == null && cmEach.getMeasureTypeId() != null) {
                channelMetadataDetails.stream().filter(cm -> cm.getMeasureTypeId().equals("5")).collect(Collectors.toList());
            } else if(cmEach.getId() != null && cmEach.getUnitOfMeasureId() != null && cmEach.getMeasureTypeId() == null) {
                channelMetadataDetails.stream().filter(cm -> cm.getId().equals("2") && cm.getUnitOfMeasureId().equals("4")).collect(Collectors.toList());
            } else if(cmEach.getId() != null && cmEach.getUnitOfMeasureId() == null && cmEach.getMeasureTypeId() != null) {
                channelMetadataDetails.stream().filter(cm -> cm.getId().equals("2") && cm.getMeasureTypeId().equals("5")).collect(Collectors.toList());
            } else if(cmEach.getId() != null && cmEach.getUnitOfMeasureId() != null && cmEach.getMeasureTypeId() != null) {
                channelMetadataDetails.stream().filter(cm -> cm.getId().equals("2") && cm.getUnitOfMeasureId().equals("4") && cm.getMeasureTypeId().equals("5")).collect(Collectors.toList());
            }
        }
sjain
  • 23,126
  • 28
  • 107
  • 185
  • 2
    `cm.getId() == "2"` - use equals – Eran Mar 05 '18 at 12:22
  • @Eran- I agree but this will give `NullPointerException` if the `getId()` is null or if the `getUnitOfMeasureId()` is null or if the `getMeasureTypeId()` is null. – sjain Mar 05 '18 at 12:24
  • @Eran - Please reopen as I have edited the question. – sjain Mar 05 '18 at 12:28
  • When `getId()` can return null you need a null-check. `cm.getId() != null && cm.getId().equals("2")`. Also `cm.getUnitOfMeasureId().equals(null)` would throw a NullPointerException or return false. –  Mar 05 '18 at 12:29

1 Answers1

1

The reason you only get the last element is that your second and third filters require that cm.getUnitOfMeasureId() and cm.getMeasureTypeId() are null. That's only true for the last element. If you only want to filter by getId(), remove the other filters:

channelMetadataDetails =
    channelMetadataDetails.stream()
                          .filter(cm -> cm.getId() != null && cm.getId().equals("2"))
                          .collect(Collectors.toList());

EDIT:

Based on your edit, you want at least one of the 3 properties to have a value, and you want to check all the not-null values:

channelMetadataDetails =
    channelMetadataDetails.stream()
                          .filter(cm -> cm.getId() != null || cm.getUnitOfMeasureId() != null || cm.getMeasureTypeId() != null)
                          .filter(cm -> cm.getId() == null || cm.getId().equals("2"))
                          .filter(cm -> cm.getUnitOfMeasureId() == null || cm.getUnitOfMeasureId().equals("4"))
                          .filter(cm -> cm.getMeasureTypeId() == null || cm.cm.getMeasureTypeId().equals("5"))
                          .collect(Collectors.toList());
Eran
  • 387,369
  • 54
  • 702
  • 768
  • I want to filter by `getId()`, `getUnitOfMeasureId()` and `getMeasureTypeId()`. But these three are coming dynamic. So which one will be null that I don't know in advance. One way is to use multiple if-else conditions to check what is null and what's not and then use filters. But that's odd. Isn't there any method in Predicates that do this for me? – sjain Mar 05 '18 at 12:36
  • 1
    @MyGod if you clarify what the exact filtering logic should be, I might be able to answer that. In the question you only asked for filtering by one field - `How to get all elements with id = 2`. – Eran Mar 05 '18 at 12:38
  • See my update in above question. I only want those objects whose elements are non-null. So I don't want `3^3 = 9` if-else conditions to check what's null and what's not null. – sjain Mar 05 '18 at 12:44
  • So if I change `channelMetadataDetail1.setId("2")` to `channelMetadataDetail1.setId("8")` then it should not give this object. But as per your edit code, it is giving `channelMetadataDetail1` whose id is even 8. I only want the non-null matching ones. – sjain Mar 05 '18 at 13:00
  • @MyGod given the `.filter(cm -> cm.getId() == null || cm.getId().equals("2"))` filter, there's no way it will pass if `cm.getID().equals("8")` – Eran Mar 05 '18 at 13:05
  • It is passing and here is the output: `[unitOfMeasureId: 3, measureTypeId: null, id: 8]`, `[unitOfMeasureId: 3, measureTypeId: 5, id: 2]`, `[unitOfMeasureId: null, measureTypeId: null, id: 2]` – sjain Mar 05 '18 at 13:07
  • So it is giving all the objects regardless of what matches and what not matches..just that what not matches is coming as `null` in the list. – sjain Mar 05 '18 at 13:09
  • @MyGod Perhaps you are not running the same code as in my answer, or perhaps there is some issue elsewhere (such as in your `ChannelMetadataDetails` class). – Eran Mar 05 '18 at 13:11
  • There was a issue in my class. I had overridden the toString method in that class `@Override public String toString() { return "unitOfMeasureId: "+unitOfMeasureId+ ", measureTypeId: "+measureTypeId+ ", id: "+id; }` – sjain Mar 05 '18 at 13:15
  • And was doing `System.out.println("channelMetadataDetails: "+channelMetadataDetails.toString());` – sjain Mar 05 '18 at 13:16
  • @MyGod Maybe it would be a good idea to move all the filtering logic to a method that returns `boolean` in the `ChannelMetadataDetails` class. This way, you would only need to do one `filter` operation in the stream. – fps Mar 05 '18 at 13:53