Reputation: 777
I have a list of GroupOffices
List<GroupOffice> officesOfTheGroup;
I want to search whether the id is not equal to groupOffice.getId (Long value) but the label is groupOffice.getLabel (String) and assign it to a boolean. The below code is working good, but is there any better approach instead of go through all items with for loop ?
public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {
List<GroupOffice> officesOfTheGroup = //some list from db..
for (GroupOffice go : officesOfTheGroup) {
if ((!go.getId().equals(groupOfficeDto.getId())) && go.getLabel().equals(groupOfficeDto.getLabel())) {
return groupOfficeDto;
}
return null:
}
Or how can I use stream ? If so, is using stream is better approach for it ?
Note: I am using Java8
Upvotes: 2
Views: 2686
Reputation: 180171
is there any better approach instead of go through all items with
for
loop ?
Notably, your code does not go through all the items if it finds an acceptable one before reaching the end of the list. But if you have only the list to work with, then there is no alternative to being prepared to check every list element. As to whether to use a for
loop, I think that's just fine.
Or how can I use stream ? If so, is using stream is better approach for it ?
It is indeed pretty fashionable these days to use streams, and although they seem to be used more than I think they should, yours is not an unreasonable use case. You might write it like this:
public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {
List<GroupOffice> officesOfTheGroup = //some list from db..
Integer officeId = groupOfficeDto.getId();
String officeLabel = groupOfficeDto.getLabel();
return officesOfTheGroup.stream()
.filter(o -> !o.getId().equals(officeId))
.anyMatch(o -> o.getLabel().equals(officeLabel))
? groupOfficeDto : null;
}
Particularly relevant here is use of the .anyMatch()
terminal operation, because it allows stream processing to finish as soon as the result is determined, like your for
loop, rather than processing the entire stream. Also note that the ID and Label against which you are comparing the offices are extracted and stored in variables before the stream expression. This allows them to be "effectively final", as is necessary for them to appear in the lambdas in the stream. It's also slightly more efficient to do it this way, instead of retrieving the same objects from the DTO over and over again -- for the for
loop case, too.
Do note that the stream version is not much simpler than the loop version, and not much easier to read, either. I don't personally see much advantage for either one over the other.
Upvotes: 2
Reputation: 2763
Try this:
public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {
...
List<GroupOffice> result = officesOfTheGroup.stream()
.filter(it -> it.getLabel().equals(groupOfficeDto.getLabel()))
.filter(it -> !it.getId().equals(groupOfficeDto.getId()))
.collect(Collectors.toList())
...
}
Upvotes: 1
Reputation: 6290
If you need boolean value you can do:
boolean b = officesOfTheGroup.stream()
.anyMatch(office -> !office.getId().equals(5) && office.getLabel().equals("London"))
Upvotes: 5