Reputation: 5454
I have a List> which is straight forward representation of a database table. I am trying to sort and apply some magic after the data is loaded into List of HashMaps. In my case this is the only hard and fast way of doing it becoz I have a rules engine that actually updates the values in the HashMap after several computations.
Here is a sample data representation of the HashMap (List of HashMap) -
{fromDate=Wed Mar 17 10:54:12 EDT 2010, eventId=21, toDate=Tue Mar 23 10:54:12 EDT 2010, actionId=1234}
{fromDate=Wed Mar 17 10:54:12 EDT 2010, eventId=11, toDate=Wed Mar 17 10:54:12 EDT 2010, actionId=456}
{fromDate=Sat Mar 20 10:54:12 EDT 2010, eventId=20, toDate=Thu Apr 01 10:54:12 EDT 2010, actionId=1234}
{fromDate=Wed Mar 24 10:54:12 EDT 2010, eventId=22, toDate=Sat Mar 27 10:54:12 EDT 2010, actionId=1234}
{fromDate=Wed Mar 17 10:54:12 EDT 2010, eventId=11, toDate=Fri Mar 26 10:54:12 EDT 2010, actionId=1234}
{fromDate=Sat Mar 20 10:54:12 EDT 2010, eventId=11, toDate=Wed Mar 31 10:54:12 EDT 2010, actionId=1234}
{fromDate=Mon Mar 15 10:54:12 EDT 2010, eventId=12, toDate=Wed Mar 17 10:54:12 EDT 2010, actionId=567}
I am trying to achieve couple of things -
1) Sort the list by actionId and eventId after which the data would look like -
{fromDate=Wed Mar 17 10:54:12 EDT 2010, eventId=11, toDate=Wed Mar 17 10:54:12 EDT 2010, actionId=456}
{fromDate=Mon Mar 15 10:54:12 EDT 2010, eventId=12, toDate=Wed Mar 17 10:54:12 EDT 2010, actionId=567}
{fromDate=Wed Mar 24 10:54:12 EDT 2010, eventId=22, toDate=Sat Mar 27 10:54:12 EDT 2010, actionId=1234}
{fromDate=Wed Mar 17 10:54:12 EDT 2010, eventId=21, toDate=Tue Mar 23 10:54:12 EDT 2010, actionId=1234}
{fromDate=Sat Mar 20 10:54:12 EDT 2010, eventId=20, toDate=Thu Apr 01 10:54:12 EDT 2010, actionId=1234}
{fromDate=Wed Mar 17 10:54:12 EDT 2010, eventId=11, toDate=Fri Mar 26 10:54:12 EDT 2010, actionId=1234}
{fromDate=Sat Mar 20 10:54:12 EDT 2010, eventId=11, toDate=Wed Mar 31 10:54:12 EDT 2010, actionId=1234}
2) If we group the above list by actionId they would be resolved into 3 groups - actionId=1234, actionId=567 and actionId=456. Now here is my question -
For each group having the same eventId, I need to update the records so that they have wider fromDate to toDate.
Meaning, if you consider the last two rows they have same actionId = 1234 and same eventId = 11. Now we can to pick the least fromDate from those 2 records which is Wed Mar 17 10:54:12 and farther toDate which is Wed Mar 31 10:54:12 and update those 2 record's fromDate and toDate to Wed Mar 17 10:54:12 and Wed Mar 31 10:54:12 respectively.
Any ideas?
PS: I already have some pseudo code to start with.
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.lang.builder.CompareToBuilder;
public class Tester {
boolean ascending = true ;
boolean sortInstrumentIdAsc = true ;
boolean sortEventTypeIdAsc = true ;
public static void main(String args[]) {
Tester tester = new Tester() ;
tester.printValues() ;
}
public void printValues ()
{
List<HashMap<String,Object>> list = new ArrayList<HashMap<String,Object>>() ;
HashMap<String,Object> map = new HashMap<String,Object>();
map.put("actionId", new Integer(1234)) ;
map.put("eventId", new Integer(21)) ;
map.put("fromDate", getDate(1) ) ;
map.put("toDate", getDate(7) ) ;
list.add(map);
map = new HashMap<String,Object>();
map.put("actionId", new Integer(456)) ;
map.put("eventId", new Integer(11)) ;
map.put("fromDate", getDate(1)) ;
map.put("toDate", getDate(1) ) ;
list.add(map);
map = new HashMap<String,Object>();
map.put("actionId", new Integer(1234)) ;
map.put("eventId", new Integer(20)) ;
map.put("fromDate", getDate(4) ) ;
map.put("toDate", getDate(16) ) ;
list.add(map);
map = new HashMap<String,Object>();
map.put("actionId", new Integer(1234)) ;
map.put("eventId", new Integer(22)) ;
map.put("fromDate",getDate(8) ) ;
map.put("toDate", getDate(11)) ;
list.add(map);
map = new HashMap<String,Object>();
map.put("actionId", new Integer(1234)) ;
map.put("eventId", new Integer(11)) ;
map.put("fromDate",getDate(1) ) ;
map.put("toDate", getDate(10) ) ;
list.add(map);
map = new HashMap<String,Object>();
map.put("actionId", new Integer(1234)) ;
map.put("eventId", new Integer(11)) ;
map.put("fromDate",getDate(4) ) ;
map.put("toDate", getDate(15) ) ;
list.add(map);
map = new HashMap<String,Object>();
map.put("actionId", new Integer(567)) ;
map.put("eventId", new Integer(12)) ;
map.put("fromDate", getDate(-1) ) ;
map.put("toDate",getDate(1)) ;
list.add(map);
System.out.println("\n Before Sorting \n ");
for(int j = 0 ; j < list.size() ; j ++ )
System.out.println(list.get(j));
Collections.sort ( list , new HashMapComparator2 () ) ;
System.out.println("\n After Sorting \n ");
for(int j = 0 ; j < list.size() ; j ++ )
System.out.println(list.get(j));
}
public static Date getDate(int days) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, days);
return cal.getTime() ;
}
public class HashMapComparator2 implements Comparator
{
public int compare ( Object object1 , Object object2 )
{
if ( ascending == true )
{
return new CompareToBuilder()
.append(( ( HashMap ) object1 ).get ( "actionId" ), ( ( HashMap ) object2 ).get ( "actionId" ))
.append(( ( HashMap ) object2 ).get ( "eventId" ), ( ( HashMap ) object1 ).get ( "eventId" ))
.toComparison();
}
else
{
return new CompareToBuilder()
.append(( ( HashMap ) object2 ).get ( "actionId" ), ( ( HashMap ) object1 ).get ( "actionId" ))
.append(( ( HashMap ) object2 ).get ( "eventId" ), ( ( HashMap ) object1 ).get ( "eventId" ))
.toComparison();
}
}
}
}
Upvotes: 0
Views: 1906
Reputation: 5454
Here is my final solution -
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.lang.builder.CompareToBuilder;
public class Tester {
boolean ascending = true ;
boolean sortInstrumentIdAsc = true ;
boolean sortEventTypeIdAsc = true ;
public static void main(String args[]) {
Tester tester = new Tester() ;
tester.printValues() ;
}
public void printValues() {
List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("actionId", new Integer(1234));
map.put("eventId", new Integer(21));
map.put("fromDate", getDate(1));
map.put("toDate", getDate(7));
list.add(map);
map = new HashMap<String, Object>();
map.put("actionId", new Integer(456));
map.put("eventId", new Integer(11));
map.put("fromDate", getDate(1));
map.put("toDate", getDate(1));
list.add(map);
map = new HashMap<String, Object>();
map.put("actionId", new Integer(1234));
map.put("eventId", new Integer(20));
map.put("fromDate", getDate(4));
map.put("toDate", getDate(16));
list.add(map);
map = new HashMap<String, Object>();
map.put("actionId", new Integer(1234));
map.put("eventId", new Integer(22));
map.put("fromDate", getDate(8));
map.put("toDate", getDate(11));
list.add(map);
map = new HashMap<String, Object>();
map.put("actionId", new Integer(1234));
map.put("eventId", new Integer(11));
map.put("fromDate", getDate(1));
map.put("toDate", getDate(10));
list.add(map);
map = new HashMap<String, Object>();
map.put("actionId", new Integer(1234));
map.put("eventId", new Integer(11));
map.put("fromDate", getDate(4));
map.put("toDate", getDate(15));
list.add(map);
map = new HashMap<String, Object>();
map.put("actionId", new Integer(1234));
map.put("eventId", new Integer(11));
map.put("fromDate", getDate(8));
map.put("toDate", getDate(30));
list.add(map);
map = new HashMap<String, Object>();
map.put("actionId", new Integer(567));
map.put("eventId", new Integer(12));
map.put("fromDate", getDate(-1));
map.put("toDate", getDate(1));
list.add(map);
System.out.println("\n Before Sorting \n ");
for (int j = 0; j < list.size(); j++) {
System.out.println(list.get(j));
}
// sort the list
HashMapComparator2 comparator = new HashMapComparator2();
Collections.sort(list, comparator);
System.out.println("\n After Sorting \n ");
for (int j = 0; j < list.size(); j++) {
System.out.println(list.get(j));
}
HashMap<String, Object> prev = null;
List<HashMap<String, Object>> same = new ArrayList<HashMap<String, Object>>();
for (HashMap<String, Object> row : list) {
if (prev != null) {
int diff = comparator.compare(prev, row);
if (diff == 0) {
same.add(row);
same.add(prev);
}
else {
merge(same);
same.clear();
}
}
prev = row;
}
merge(same);
System.out.println("\n After Merging \n ");
for (int j = 0; j < list.size(); j++) {
System.out.println(list.get(j));
}
}
private void merge(List<HashMap<String, Object>> same) {
if (!same.isEmpty()) {
// Now find min max
Date min = null;
Date max = null;
for (HashMap<String, Object> i : same) {
Date from = (Date) i.get("fromDate");
Date to = (Date) i.get("toDate");
if (min == null) {
min = from;
}
else if (from.before(min)) {
min = from;
}
if (max == null) {
max = to;
}
else if (to.after(max)) {
max = to;
}
}
for (HashMap<String, Object> i : same) {
i.put("fromDate", min);
i.put("toDate", max);
}
}
}
public static Date getDate(int days) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, days);
return cal.getTime() ;
}
public class HashMapComparator2 implements Comparator
{
public int compare ( Object object1 , Object object2 )
{
if ( ascending == true )
{
return new CompareToBuilder()
.append(( ( HashMap ) object1 ).get ( "actionId" ), ( ( HashMap ) object2 ).get ( "actionId" ))
.append(( ( HashMap ) object2 ).get ( "eventId" ), ( ( HashMap ) object1 ).get ( "eventId" ))
.toComparison();
}
else
{
return new CompareToBuilder()
.append(( ( HashMap ) object2 ).get ( "actionId" ), ( ( HashMap ) object1 ).get ( "actionId" ))
.append(( ( HashMap ) object2 ).get ( "eventId" ), ( ( HashMap ) object1 ).get ( "eventId" ))
.toComparison();
}
}
}
}
Upvotes: 0
Reputation: 11
import java.util.*;
public class hasmap {
public static void main(String[] args) {
List <Map> result=new ArrayList();
Map emp1 = new HashMap();
emp1.put("Name", "wivek");
emp1.put("EmpID", Long.valueOf("1077"));
emp1.put("JoinDate",new Date());
emp1.put("MobileNo",Long.valueOf("1234567890"));
Map emp2 = new HashMap();
emp2.put("Name", "aww");
emp2.put("EmpID", Long.valueOf("10"));
emp2.put("JoinDate",new Date());
emp2.put("MobileNo",Long.valueOf("1234567890"));
Map emp3 = new HashMap();
emp3.put("Name", "bww");
emp3.put("EmpID", Long.valueOf("10"));
emp3.put("JoinDate",new Date());
emp3.put("MobileNo",Long.valueOf("1234567890"));
result.add(emp1);
result.add(emp2);
result.add(emp3);
System.out.println("\n Before Sorting \n" );
for(int j = 0 ; j < result.size() ; j ++ )
System.out.println(result.get(j));
srt(result,"Name");
}
private static void srt(List<Map> result, final String n) {
Collections.sort(result, new Comparator(){
public int compare(Object o1, Object o2) {
Map e1 = (Map) o1;
Map e2 = (Map) o2;
return e1.get(n).toString().compareToIgnoreCase(e2.get(n).toString());
}
});
System.out.println("\n After Sorting \n" );
for(int j = 0 ; j < result.size() ; j ++ )
System.out.println(result.get(j));
}
}
Upvotes: 1
Reputation: 22292
You want to sort your list ? Then use a TreeSet
and a customized Comparator. This way, each time a Map is added, it will be set at the correct position.
Notice that, if you want to change sort algorithm during list usage, you can instead use Collections#sort
.
And finally notice I consider your way of sorting things quite weird, since sorting your DB data can usually be done more consistently by using a SORT predicate in your SQL statement.
Upvotes: 0
Reputation: 66156
As I understand from your description all your data is retrieved from DB. Why don't you do sorting and grouping stuff by means of SQL?
UPD (after comment): then I definitely like a solution with
TreeMap<Integer, List<DbRecord>>
where actionIds are keys of this TreeMap and each item of your list is DbRecord object.
In this case sorting and grouping problems will be solved implicitly, and you'll have only to iterate through the map in order to update dates values.
Even better approach is to use TreeMultimap from Google Collections.
Upvotes: 2
Reputation: 57274
A number of posts suggest a Custom Comparator and using natural sorting provided by a treeset or treemap, e.g
public class MapComparator implements Comparator<Map>{
public MapComparator(String key, boolean asc){..set value properties ...}
public int comparae(Map a, Map b) { ... compare a.get(key), b.get(key) ... }
}
Since your data is also changing on the fly, I think you have an additional complication, in that reordering your collection of maps for one operation may invalidate the ordering for a previous operation. If you're doing operations serially, and once you've done a sort you don't need to preserve the values, that's fine, but if there's ever any point where you'll simultaneously need the access to 2 different sort results it will break, since each sort overwrites (or at least can potentially break) the previous. For that you could either
Upvotes: 0
Reputation: 8222
It sounds like you really want to just have one object per actionId/ eventId pair. Have you considered instead using something like a factory to generate a new object / modify an existing object? Rough code:
public class ObjectFactory{
class Key{
String eventId, actionId;
}
HashMap<Key, ObjectXYZ> objects = new HashMap<...,...>();
ObjectXYZ getObject(String actionId, String eventId, Date from, Date to){
Key k = new Key(actionId, eventId);
ObjectXYZ ret = objects.get(k);
if(ret == null){
ret = new ObjectXYZ(actionid, eventId, from, to);
objects.put(k, ret);
}else{
if(from < ret.from) ret.from = from;
if(to < ret.to) ret.to = to;
}
return ret;
}
}
Then you would not need to create any extra objects and would have fewer objects to sort (if you would need to sort them at all).
Upvotes: 0