Java collections: how to split a sorted list into subcategories

Let's say I have a list (EG: LinkedList<SomeObject> , which contains elements ordered by a specific attribute (EG: SomeObject.someValue() ). This attribute can and will usually be repeated often / it is not unique, BUT is never null .

Is there a convenient way to divide this into several lists, with each list containing only its equal in a cardinal order? Also, can this only be done with iterating the list? For example, the source list:

 1, 1, 1, 2, 2, 3, 3, 3 

Desired Lists:

 1, 1, 1 2, 2, 3, 3, 3 
+4
source share
6 answers

Not too convenient, but:

  • run the loop. Save the previous item and compare it with the current one.
  • if the previous one is different from the current one (use equals(..) and be careful with null ), then create a new List or use list.subList(groupStart, currentIdx)
+10
source

You can use Apache CollectionUtils for this, where the "list" is the source list and the "value" is the current value of the objects you want to extract the subscriptions for:

 Collection<SomeObject> selectedObjects = CollectionUtils .select(list, new Predicate() { boolean evaluate(Object input) { return ((SomeObject) input).someValue().equals(value); } }); 

This approach means using a well-known and well-tested library (which is always good), but the disadvantage is that you will iterate over the list once for each subnet you need.

+4
source

It’s pretty accurate that there is no Java API method for this. However, you can write:

  // This assumes your list is sorted according to someValue() // SomeValueType is the type of SomeObject.someValue() public Map<SomeValueType, List<SomeObject>> partition(List<SomeObject> list) { Object currValue = null; HashMap<SomeValueType, LinkedList<SomeObject>> result = new HashMap<SomeValueType, LinkedList<SomeObject>>(); LinkedList<SomeObject> currList = null; for (SomeObject obj : list) { if (!obj.someValue().equals(currValue()) { currValue = obj.someValue(); currList = new LinkedList<SomeObject>(); result.put(currValue, currList); } currList.add(obj); } } 

This will return you the HashMap subscriptions, where the key is someValue and the value is the associated list of partitioned files. Note that I have not tested this, so do not just copy the code.

EDIT: did this hashmap return instead of arraylist.

+3
source

If you use Google Guava-libaries :

 import com.google.common.collect.HashMultiset; import com.google.common.collect.Lists; public class Example { public static void main(String[] args) { HashMultiset<Integer> ints = HashMultiset.create(); ints.addAll(Lists.newArrayList(1, 1, 1, 2, 2, 3, 3, 3)); System.out.println(ints); } } 

Output:

 [1 x 3, 2 x 2, 3 x 3] 

If you need to calculate how many x elements you use ints.count(x); if you have value types, you don't need more than just counting.

+3
source

This should work (unchecked, but I'm sure everything is in order, this also assumes the contents of the list are sorted):

 public static List[] getEquivalentSubLists( List parent ) { List cloneList = parent.clone(); Collections.sort(cloneList); ArrayList<List> returnLists; int end; while (cloneList.size() > 0) { end = cloneList.lastIndexOf(cloneList.get(0)); returnLists.add(cloneList.subList(0, end)); cloneList.removeAll(cloneList.subList(0, end)); } return returnList.toArray(); } 
+1
source

All Articles