1

I created a class name objectA that has lets say 4 variable: Date time; String text; int var1, int var2

I need to create a list of ObjectA(). And then group them first by Time, second by var1, and then by var2. This is because i want to be able to compare lists that has different var2 but the same var1; or lists that has the same var2 but different var1.

I end up using "List< List< List< objectA>>>" which works fine i guess, but it doesnt looks great. And i dont think this is a good practice. Does anyone know any Datastructure or Tree or other ideas with which i could implement instead of List within List within List.

The list of object may look something like this

Almost similar question has actually been ask here: List of Lists of Lists .But the answer are just not what i was looking for. Please pardon me if this is still consider against the rule.

Community
  • 1
  • 1
udon
  • 93
  • 1
  • 5
  • Why do you need `List>>` ? – Devendra Lattu Apr 13 '17 at 19:47
  • Your picture clearly shows tree, every node in tree is list – Iłya Bursov Apr 13 '17 at 19:48
  • please be more specific. Your image looks like a tree structure. why dont u use them? Write your own datastructure – osanger Apr 13 '17 at 19:49
  • The picture is just for illustration how the list is group up. The top shows the whole list of object. On the second row, the list of object is separated by var1, and on the third row, the list of object is separated by var2. I could make such structure but then i will have duplicate objects (in this case every object is duplicate 3 times) – udon Apr 13 '17 at 19:52
  • I have change the picture to better illustrate what i mean. – udon Apr 13 '17 at 20:21
  • I think the picture leads to confusion. People answering your question think that you actually want to create a tree from your list. – fps Apr 13 '17 at 20:22

4 Answers4

2

This is an example of a simple tree structure for your problem.

public class Tree {

private Node root;

public Tree(List<YourObject> rootData) {
    root = new Node();
    root.data = rootData;
    root.children = new ArrayList<Node>();
}

public static class Node {
    private List<YourObject> data;
    private Node parent;
    private List<Node> children;
}
}

Your can build a simple tree and run all tree and graph-algorithms on this simple structure.

osanger
  • 2,276
  • 3
  • 28
  • 35
1

The ideal structure to group objects by some attribute is a Map of Lists, where each key of the map corresponds to each different value of the attribute along the list of objects, and each value of the map is a sublist of all the objects whose attribute matches the key.

Let's start grouping by a single attribute. Using streams is quite easy to accomplish what you want:

Map<Date, List<ObjectA>> groupsByDate = 
    yourList.stream()
        .collect(Collectors.groupingBy(ObjectA::getTime));

This assumes ObjectA has a getTime method.

Now, Collectors.groupingBy has an overloaded version that accepts what is called a downstream collector, meaning that you can collect the objects that match a value into another structure different than a List.

For example, you can collect to a second Map that groups objects by a second criteria, in your case this would be by var1:

Map<Date, Map<String, List<ObjectA>>> groupsByDateAndVar1 = 
    yourList.stream()
        .collect(Collectors.groupingBy(
            ObjectA::getTime, 
            Collectors.groupingBy(ObjectA::getVar1)));

This assumes ObjectA has also a getVar1 method.

Finally, if you need to group by a third nested criteria, you could do it in a similar way:

Map<Date, Map<String, Map<String, List<ObjectA>>>> groupsByDateAndVar1AndVar2 = 
    yourList.stream()
        .collect(Collectors.groupingBy(
            ObjectA::getTime, 
            Collectors.groupingBy(
                ObjectA::getVar1,
                Collectors.groupingBy(ObjectA::getVar2))));

This assumes ObjectA has also a getVar2 method.

fps
  • 33,623
  • 8
  • 55
  • 110
  • I have though of using maps, but refrain from doing "maps within maps within maps". Unless this is really better than "list within list within list". – udon Apr 13 '17 at 20:32
  • @udon It is better in the sense that you can access each submap by the value of the attribute, while with lists you have to go by index. Maybe you could use [Guava tables](https://github.com/google/guava/wiki/NewCollectionTypesExplained#table) for this. – fps Apr 13 '17 at 20:34
  • I see. The Guava Tables looks promising though. Thanks :) – udon Apr 13 '17 at 20:56
  • @udon As you want to group by three variables, I'm afraid you'll have to group to a map of tables of lists (or to a table of maps of lists, whatever you think is better) – fps Apr 13 '17 at 21:59
0

a List<List<Object>> is probably what you want if you want to group by the first variable and then subgroup by the second

You could also do a Tree, up to you

Ben Arnao
  • 492
  • 5
  • 11
0

If that's always the way you want to sort; by time, then val1, then val2, implement Comparable in your ObjectA class. Something like

public int compareTo(Object that) {
    //check for null
    // check for instanceOf ObjectA
    // cast from Object to ObjectA
    int result = this.time.compareTo(that.time);
    if (result == 0) {
       // time comparison was the same
       result = this.var1.compareTo(that.var1);
       if (result == 0) {
           // time and var1 comparisons were the same
           result = this.var2.compareTo(that.var2)
       }
    }
    return result;
}

and then just sort() one list.

geneSummons
  • 907
  • 5
  • 15