Reputation: 6638
I have an ArrayList
containing Objects that have a date value.
Now I want to manage to create a new ArrayList
for each year that contains all the Objects from the main ArrayList
that have the same year in their date Value.
So all Objects from 2010 go in one List, all from 1999 in another.
Upvotes: 2
Views: 10280
Reputation: 383746
You need a Map<Year,List<DatedObject>>
, maybe even SortedMap
like a TreeMap
.
You can also use multimap from Guava.
Essentially you map from each year (perhaps just an Integer
), the List<DatedObject>
that belong in that year.
And since years have a natural sorting order, you may want to see if SortedMap
provides you with functionalities that you need. Most likely the answer is yes.
Here's a snippet in Java that shows you how you can populate the map. Note also that NavigableMap
is used instead of SortedMap
; NavigableMap
allows inclusive range queries (see related question).
class DatedObject {
final String name; final int year;
DatedObject(String name, int year) {
this.name = name; this.year = year;
}
@Override public String toString() {
return String.format("%s (%d)", name, year);
}
}
List<DatedObject> masterList = Arrays.asList(
new DatedObject("A", 2010),
new DatedObject("B", 2009),
new DatedObject("C", 2006),
new DatedObject("D", 2010),
new DatedObject("E", 2009),
new DatedObject("F", 2011)
);
NavigableMap<Integer,List<DatedObject>> objectsByYear =
new TreeMap<Integer,List<DatedObject>>();
for (DatedObject obj : masterList) {
List<DatedObject> yearList = objectsByYear.get(obj.year);
if (yearList == null) {
objectsByYear.put(obj.year, yearList = new ArrayList<DatedObject>());
}
yearList.add(obj);
}
System.out.println(objectsByYear);
// prints "{2006=[C (2006)], 2009=[B (2009), E (2009)],
// 2010=[A (2010), D (2010)], 2011=[F (2011)]}"
System.out.println(objectsByYear.get(2011));
// prints "[F (2011)]"
System.out.println(objectsByYear.subMap(2007, true, 2010, true));
// prints "{2009=[B (2009), E (2009)], 2010=[A (2010), D (2010)]}"
If you absolutely insists on a List<List<DatedObject>> partitionedList
, then build the map as above, and simply follow it with:
List<List<DatedObject>> partitionedList =
new ArrayList<List<DatedObject>>(objectsByYear.values());
System.out.println(partitionedList);
// prints "[[C (2006)], [B (2009), E (2009)], [A (2010), D (2010)], [F (2011)]]"
You can also use Multimap
from Guava, and Multimaps.index
utility method as follows:
Multimap<Integer,DatedObject> mmap = Multimaps.index(
masterList,
new Function<DatedObject, Integer>(){
@Override public Integer apply(DatedObject from) {
return from.year;
}
}
);
System.out.println(mmap);
// prints "{2010=[A (2010), D (2010)], 2009=[B (2009), E (2009)],
// 2006=[C (2006)], 2011=[F (2011)]}"
com.google.common.collect.Multimap
com.google.common.collect.Multimaps
com.google.common.base.Function
Upvotes: 14
Reputation: 40851
The Multimaps.index() method in Guava will do this for you.
Upvotes: 4
Reputation: 1050
Map<Integer, List<YourObject>> yearLists = new HashMap<Integer, List<YOurObject>>();
List<YourObject> originalList = ...; //initialized or received from somewhere
for (YourObject object : originalList) {
int year = object.getDate().getYear(); //or something
List<YourObject> yearList = yearLists.get(year);
if (yearList == null) {
yearList = new ArrayList<YourObject>();
}
yearList.add(object);
yearLists.put(year, yearList);
}
I hope I didn't make much mistakes there..
Upvotes: 4