0

Need to go through on a complex data structure and modify external variables from the algorithm.

I have tried to do it with stream but as far as I know it is not thread safe, can be race conditions...

Is there a better way than this below copied approach?

List<ObjectA> externalVariable = new ArrayList<>();
List<ObjectA> externalVariable2 = new ArrayList<>();

if (objectA != null) {
    externalVariable.add(objectA);

    for (ObjectB objectB : objectA) {
        if (objectB.getObjectC() != null) {
            for (ObjectD objectD : objectB.getObjectC()) {
                if (objectD.getObjectE() != null) {
                    for (ObjectE objectE : objectD.getObjectE()) {
                        if (objectE.getObjectF() != null) {
                            for (ObjectG objectG : objectE.getObjectF()) {
                                objectG.setSomething("BlaBla");

                                if (objectG.getOjectH() != null && objectG.getOjectH().getObjectI() != null) {
                                    for (ObjectI objectI : objectG.getOjectH().getObjectI()) {
                                        externalVariable2.add(objectI);
                                        ObjectJ objectJ = getRelevantOjectJ(objectA.getId(), objectI.getId());
                                        objectI.setObjectJ(objectJ);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
5
  • 1
    "Is there a better way than this below copied approach?" - If the code works as intended and you want a review, the question might be better suited for CodeReview. Commented Jul 28, 2019 at 11:07
  • Well, using streams is not less or more prone to race conditions as a simple for loop, as long as the stream is sequential. Commented Jul 28, 2019 at 11:08
  • how does this make sense? for (ObjectB objectB : objectA) Commented Jul 28, 2019 at 11:10
  • By the way, if an object is a sort of collection or stream (like objectA in your case), it should never be null. Commented Jul 28, 2019 at 11:12
  • @PatrickParker If ObjectA impelements Iterable<ObjectB> (which it must if the code works), this makes perfect sense (syntacticall, at least) Commented Jul 28, 2019 at 11:12

1 Answer 1

1

Race conditions occur when more than one thread execute concurrently statements that modify a shared state.
If your current code is thread safe, it will still be with stream while you don't use the parallel stream feature.
About your actual code : we can consider it is an arrow code, not easily to read and to maintain.

You have different approaches to reduce the global nesting but I don't encourage streams here because you don't collect into a result but you mutate external objects. That is not a use case for stream.

You can remark in your current code that you iterate on many collections explicitly while the applied logic don't care about most of them.

Here, all that is performed only to get ObjectG instances, the remaining is not used then :

for (ObjectB objectB : objectA) {
    if (objectB.getObjectC() != null) {
        for (ObjectD objectD : objectB.getObjectC()) {
            if (objectD.getObjectE() != null) {
                for (ObjectE objectE : objectD.getObjectE()) {
                    if (objectE.getObjectF() != null) {
                        for (ObjectG objectG : objectE.getObjectF()) {

So encapsulate all of that into a method that collect ObjectG instances and return them.
Note that it could be written without stream but also with since for collecting them you don't need to modify a shared state.

Finally you method could be simplified as :

Collection<ObjectG> objectsG = collectG(objectA); // extracted method

for (ObjectG objectG : objectsG) {
    objectG.setSomething("BlaBla");

    if (objectG.getOjectH() != null && objectG.getOjectH().getObjectI() != null) {
        for (ObjectI objectI : objectG.getOjectH().getObjectI()) {
            externalVariable2.add(objectI);
            ObjectJ objectJ = getRelevantOjectJ(objectA.getId(), objectI.getId());
            objectI.setObjectJ(objectJ);
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.