0

I have a parentObject with collection of childObjects. These childObjects have distinct child names. So if I filter the child objects with childName, only one object would be returned. Populating values using forEach works fine,but there is no need to use forEach in this case as only one child object is returned. This is my current code.

Child childOne = new Child("ken");
Child childTwo = new Child("mathew");

Collection<Child> collectionOfChildObjects = new ArrayList<>();
collectionOfChildObjects.add(childOne);
collectionOfChildObjects.add(childTwo);
parentObject.setCollectionOfChildObjects(collectionOfChildObjects);

String value="ken";
parentObject.getCollectionOfChildObjects().stream()
    .filter(childObject-> Objects.equals(
        value,
        childObject.getChildName()))
    .forEach(childObj-> {
        childObj.setAge(5);
    });

The Child class for the same is shown below.

class Child(){

private String name;
private int age;

public Child(String name){
  this.name = name;
}

public String getName(){
  return this.name;
}

}

Can someone please explain how to populate values without the use of forEach.

Naman
  • 27,789
  • 26
  • 218
  • 353
ali
  • 29
  • 7
  • `findAny().ifPresent(...)`. If something you tried "does not work", then post what you tried, and explain precisely how it didn't work. That way we can explain why what you tried didn't work, and give explanations or hints in order to fix it. – JB Nizet Jan 17 '20 at 14:44
  • @runefist getCollectionOfChildObjects() return basically a Collection of objects. It is with these objects i need to alter the value. – ali Jan 17 '20 at 14:46
  • @JBNizet I wouldn't use that, if it finds multiple values of "ken" (in this example) it will just change 1, I don't think he wants that behaviour. Maybe this post will help you: https://stackoverflow.com/questions/22694884/filter-java-stream-to-1-and-only-1-element – runefist Jan 17 '20 at 14:48
  • @AlistarFernandez check the link I gave, it is to make sure there's only 1 ken and if so then change it. – runefist Jan 17 '20 at 14:49
  • @runefist if the OP expected multiple matching values and wanted to change all, then the posted solution with forEach would be the right one. – JB Nizet Jan 17 '20 at 14:50
  • @JBNizet I think he wants only 1 object to return as he says destinct child names, but if he is sure that the filter will ALWAYS return just one object the forEach has no performance impact... – runefist Jan 17 '20 at 14:52
  • Yes. But that is different from "checking there is at most one". It just means "I know there is at most one, and I want to stop looping as soon as I found it". – JB Nizet Jan 17 '20 at 14:53
  • We'll never know what he exactly wants XD – runefist Jan 17 '20 at 14:54
  • Yes only one object is returned after filter and will always return atmost one object @JBNizet . After I find the object i just need to populate age into the object. Is forEach the right approach to populate ? – ali Jan 17 '20 at 15:01
  • You can use after filter ".peek( child -> child.setAge(5))" and ".findFirst()" – user1234SI. Jan 17 '20 at 15:36
  • @AlistarFernandez No. The right approach is to use findAny().ifPresent(...), as I said in my very first comment. – JB Nizet Jan 17 '20 at 15:55
  • 1
    @runefist of course the forEach has a performance impact. Streams are lazy, so the filter would keep searching for other matches until reaching the end of the collection. findAny would stop the iteration as soon as a matching element is found. – JB Nizet Jan 17 '20 at 15:57
  • @JBNizet , if i use findAny() , can you please explain how can i modify the values in childObject. findAny() returns optional which is inturn required to check ifPresent() which returns boolean. After this check how can i modify the values. – ali Jan 17 '20 at 16:38
  • 1
    Optional.ifPresent() doesn't return a boolean. https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#ifPresent-java.util.function.Consumer-. It returns void. And it takes a consumer as argument. It thus has the exact same signature as Stream.forEach(). So you use it the same way as you're already using forEach: by passing a lambda that modifies the object contained in the optional. The exact same lambda you're passing to forEach. – JB Nizet Jan 17 '20 at 16:41

0 Answers0