0
\$\begingroup\$

I am working on a rewrite project, where I'm supposed to change the enhanced for-loop code used in java6 to the newer forEach loop. Similarly, we have to use Streams API as heavily as possible.

Below is the complete scenario followed by code sample

  1. Iterate over each element of List<String> list.
  2. If Map<String, A> has each as key, take the corresponding A value from the Map.
  3. A has an instance variable, List<B> which is a list of class B objects.
  4. If List<B> is null initialize new List<B> and put some value inside it. Else just add a new value to Existing List<B>.

The complete code for the problem is below:

    class A{
        List<B> values;

    }

    class B{

    }

    //Assume some values
    List<String> list = ["val1","val2"];
    //Assume some values
    Map<String, A> map = { "val1" : [A object] , "val2" : [A object] };
    B b = new B();

    //Iterate over every value in list
    for(String each: list){
        //if map has a key with the value inside the list
        A a = map.get(each);

        //A has a list called "values" of B class objects. If that list is not null or empty add a new B object (b )in our case to the a List else initialze a new List and add the value there.
        if(a.values != null && !a.values.isEmpty()){
            a.values.add(b);
        }else{
            List<B> bList = new ArrayList<>();
            bList.add(b);
            a.values = bList;
        }
    }
\$\endgroup\$

closed as unclear what you're asking by Emily L., Toby Speight, Ludisposed, Graipher, Dannnno Jan 9 '18 at 16:39

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ What makes you think this isn't java 8? Sure there might be an alternative implementation that uses streams, but that also gives more overhead so I doubt it would be better here. As it is now I don't really see the point of this question. The code shown is so vague that I doubt it actually belongs on this site. Maybe I'm just missing something so I'll just downvote and let other people decide what they want to do with it. \$\endgroup\$ – Imus Jan 9 '18 at 8:32
  • \$\begingroup\$ @Imus I posted the same question in stackoverflow and was asked this question belongs to this site so I moved it here. Additionally, I am asked to move all java6 code which is like this to the latest java8 (streams api) way. I am not very sure how to do this so I asked. If you want me to explain further I can do that. \$\endgroup\$ – utkarsh31 Jan 9 '18 at 8:49
  • 2
    \$\begingroup\$ Here's a blog with interesting counter arguments that you can pass on to your superiors to challenge their decission on using streams only. Streams CAN be useful but I wouldn't force using them everywhere without thinking ... \$\endgroup\$ – Imus Jan 9 '18 at 12:54
  • \$\begingroup\$ @TobySpeight Thank you for the insight, I have rephrased the question please update if there is still something missing. It would be greatly appreciated if you could remove the downvote and on hold if the rephrased question fits the website standards \$\endgroup\$ – utkarsh31 Jan 10 '18 at 4:24
2
\$\begingroup\$

Regardless of the java version you use, the business logic, which decides whether the object should be added and in which way, is placed in a non-OO programming paradigm. Instead of walking through other objects private parts, just add an appropriate method in the object itself and call that method:

class A {
   List<B> values;

   public void addB(B newVal) {
      if(values != null && !values.isEmpty()) {
         values.add(newVal);
      }
      else {
         values = new ArrayList<>();
         values.add(newVal);
      }
   }
}

Then, the actual call of the logic is simple and clean, no matter whether you use a loop or a stream:

list.stream()
   .map(key -> map.get(key))  // alternative: map::get
   .forEach(a -> a.addB(b));

or

for(String key : list)
    map.get(key).add(b);
\$\endgroup\$
2
\$\begingroup\$

Non sure what is the purpose to write your code in a java 8 way, please explain this part.

I think you mean using streams.

Anyway, here is an example.

Comparing with your code I introduced a filter that guarantee the key in list exists as a key in the map.

The other part are equivalent.

UPDATE: I added the _map_part that I had forgot previously. The map can transform your list of string in a new list of different types.

In this case you use the list of string as a filter to get elements from the map. You don't want to operate on the String keys, instead you want to access the map values that are objects of type A.

list.stream()
    .filter(key -> (map.containsKey(key)))
    .map(key -> (map.get(key)))
    .forEach(a -> {
         if (a.values == null)
             a.values = new ArrayList<>();

         a.values.add(b);
     });

I think the main difference for this approach, compared with the old fashion is that you describe more your intentions, and the purpose of the code emerges much clearly.

But in trivial examples like yours the differences are not so clear and the functional approach seems much complicated.

Not all the case can be converted properly in this way, there are still cases where you whould prefer the loop over the streams.

\$\endgroup\$
  • \$\begingroup\$ Thanks a lot, I agree that for cases like these we should use normal java6 way but my current project is a rewrite and they want all things to be done using streams. Anyways let me verify my scenario once with this code. \$\endgroup\$ – utkarsh31 Jan 9 '18 at 8:55
  • \$\begingroup\$ @utkarsh31 I updated my answer as I saw I missed a part. \$\endgroup\$ – Mario Santini Jan 9 '18 at 12:47
0
\$\begingroup\$

Here is you code example. For simplicity, I have removed the object B with String. basically forEach () loop can be use to achieve the same. However, for more complex logic, I would doing it with conventional java for loops to keep the code readable.

list.stream().forEach(val -> { A a = map.get(a); if(a.values != null && !a.values.isEmpty()){
    a.values.add("new obj");
}else{
    List<String> bList = new ArrayList<>();
    bList.add("new obj");
    a.values = bList;
}

}); 
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.