How to optimally read a list of ArrayList dependencies?

2

I have 4 classes, each class has a ArrayList , where the last element depends on another ArrayList : Example Genêro-> Artists-> Albuns-> Songs

To read the songs I'm doing the following.

for (Genero ge : objeto.getLista()) {
for (ArtistaObj art : ge.getArtistas()) {
     for (AlbunsObj alb : art.getAlbuns()) {
          for (MusicasObj mus : alb.getMusicas()) {
          }
      }
 }
Within each for I use the getters to get all the items in the list, I'm using this to write to a bank and I think it's half hog, because in the Musicas table I'm using 4 for .

    
asked by anonymous 10.07.2015 / 22:59

2 answers

3

Given the description of the problem, unless I have not understood something, there is nothing better that can be done.

If you have any unexplained details, you may eventually find an optimization but there is no miracle. Only if there is a criterion that makes it easier to take some shortcut.

One thing you can do is have a single list that has all the data, but it will hardly be a good idea, easy on one side, difficult on another.

Even with this solution, you may have a for . But so what? Why is this a better code? Just because you have fewer links? This does not mean that the code is better written. In any case, it would probably have to have three if to identify the breach of the grouping, so maybe it would be even worse. And another, changes the data structure because of the algorithm. So yes, it would be a beautiful practice in most situations.

And understand that good or bad practice refers to common cases in a large number of cases. They can not be followed in all cases.

What you can do is separate this into methods for each interaction, so you would only have a for in each method. But it would still have 4 for . Does this make the code better? In some chaos, yes. But not necessarily, it depends on the goal. Separating too much can bring as much trouble as heaping too much. It would be something like this (roughly):

void getGeneros(ArrayList biblioteca) {
    for (Genero genero : biblioteca.getLista()) {
        getArtistas(genero);
    }
}

void getArtistas(ArrayList genero) {
    for (Artista artistas : genero.getLista()) {
        getAlbuns(artistas);
    }
}

void getAlbuns(ArrayList artista) {
    for (Album album : artista.getLista()) {
        getMusicas(album);
    }
}

void getMusicas(ArrayList album) {
    for (Musica musica : album.getLista()) {
        GravaMusica(musica);
    }
}

It's just an example. I have doubts if it is better, I think it got worse, it got repetitive depending on what each GetLista() does. Anyway I think the names of variables and types are better defined there. Since you like good practice, try to name everything well in your program, this helps a lot. It could be a better example but I do not know the whole context.

If the problem is performance it may be possible to break the operation and put the processors to work in parallel, but then the problem would already be different from what was described. And it may not even be worth the effort.

    
11.07.2015 / 00:48
0

Use a Functional Programming Style

In the question that you have done, there is only this language and programming that you put in and another one that is geared towards Java 8. In the end I mention one more option, but that involves JPA

For each genre, record the same, and return the nested list of Artists it to the next

Or formally: Apply the save function to the Genero parameter - the result of the application of the function is the same is the List of Generals

Let's go to the code

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
        class MusicasObj {
        }
        class AlbunsObj {
            List<MusicasObj> listMusic = new ArrayList<>();
        }
        class ArtistaObj {
            List<AlbunsObj> listAlbuns = new ArrayList<>();
        }
        class Genero {
            List<ArtistaObj> listArts = new ArrayList<>();
        }
        //Simpleficacão da classe DAO, aqui vc terá o seu método que grava os dados do Genero no Banco, vc precisará de mais DAOs
        class GenDAO{
            Genero save(Genero gen){System.out.println("salvar seu genereo"+gen);return gen;}
        }
        GenDAO dao = new GenDAO();
        List<Genero> listGenero = new ArrayList<>();
        listGenero
            .forEach(g -> dao.save(g)
                    .listArts //Passe a funcão que le os valores do genero e grava ele
                        .forEach(a -> a.listAlbuns
                            .forEach(al -> al.listMusic
                                .forEach(m -> System.out.println(m)))));
    }
}

(Please note, how these class definitions within the main method are for the purpose of explanation)

The main difference is a reduction of verbosity, however you need to be accustomed to writing Lambda Expressions, based on Lambda Calculus - The other option is through an ORM Framework - Object Relational Mapping, in this case, I recommend JPA - you map your entities, to database tables creating relationships, among them through metadata - annotations - finally , the implementation of JPA like Hibernate will do all the work of inserting and updating the tables, and you do not need to create all this code.

Example with JPA: link

Just one more detail, this sample code is not complete, you will need to change it and embrace it.

    
11.07.2015 / 15:05