Sorting collections based on nested collections

D

Doug Poland

Hello,

Is it possible to use a comparator, or other sorting technique, to sort
a collection has fields that are themselves collections, and, use fields
from the nested collection the sort criteria?

For example, I have an ArrayList (POList) of Purchase Order objects
(PO). Currently I use a comparator to sort based on fields of the
objects in POList that are not collections i.e., String, Date, etc.

However, one of the fields in POList is an ArrayList (LineItemsList) of
Line Item Details objects (LineItems). There may be zero, one, or many
LineItems objects in the POList.

Let's say a PO has a getCustomerName field and a LineItems has a
getDeliveryDate field. I'd like to sort the POList based on
getCustomerName from the PO object and getDeliveryDate from the many
LineItems objects.

I've been googling and have turned up nothing so far. Thanks for your help!
 
V

VisionSet

Doug Poland said:
For example, I have an ArrayList (POList) of Purchase Order objects
(PO). Currently I use a comparator to sort based on fields of the
objects in POList that are not collections i.e., String, Date, etc.

However, one of the fields in POList is an ArrayList (LineItemsList) of
Line Item Details objects (LineItems). There may be zero, one, or many
LineItems objects in the POList.

Are you saying that POList extends ArrayList and collects PO objects, but
also has another ArrayList as an attribute, and this collects LineItem
objects?

ie

class POList extends ArrayList {

ArrayList myLineItemObjects;
}

What do you mean by field?
 
D

Doug Poland

VisionSet said:
Are you saying that POList extends ArrayList and collects PO objects, but
also has another ArrayList as an attribute, and this collects LineItem
objects?

ie

class POList extends ArrayList {

ArrayList myLineItemObjects;
}

What do you mean by field?
Hope I can explain it adequately... POList is implemented as a simple
ArrayList, it's not a class. POList's members are PO objects. Each PO
object has attributes or fields (I think that's the proper terminology
from a JavaBean perspective). So a PO has a getter and setter for
customerName, poNumber, poDate, etc. One of the PO fields/attributes is
lineItems of type List. It is implemented as an ArrayList. Each item
in this ArrayList is a LineItems object, with getters/setters of it's
own. Does that make sense?
 
V

VisionSet

Doug Poland said:
Hope I can explain it adequately... POList is implemented as a simple
ArrayList, it's not a class. POList's members are PO objects. Each PO
object has attributes or fields (I think that's the proper terminology
from a JavaBean perspective). So a PO has a getter and setter for
customerName, poNumber, poDate, etc. One of the PO fields/attributes is
lineItems of type List. It is implemented as an ArrayList. Each item
in this ArrayList is a LineItems object, with getters/setters of it's
own. Does that make sense?

Got you, so you want it ordered like this:

Customer: Alpha
LineItem: Early Date
LineItem: Late Date
Customer: Beta
LineItem: Early Date
LineItem: Late Date

No hang on you want to order POList by LineItem date & CustomerName.
So order by customer name 1st then LineItem date ie equal customer names are
then ordered by LineItem date?
But which LineItem?, an average the 1st...
 
D

Doug Poland

VisionSet said:
Got you, so you want it ordered like this:

Customer: Alpha
LineItem: Early Date
LineItem: Late Date
Customer: Beta
LineItem: Early Date
LineItem: Late Date

No hang on you want to order POList by LineItem date & CustomerName.
So order by customer name 1st then LineItem date ie equal customer names are
then ordered by LineItem date?
But which LineItem?, an average the 1st...
Close :) I'll modify your example...


Customer: Alpha
LineItem01: Quantity=20, Status=Delivered, Date=09/21/2003
LineItem02: Quantity=40, Status=Shipped, Date=09/23/2003
Customer: Beta
LineItem01: Quantity=60, Status=Cancelled, Date=09/24/2003
Customer: Charlie
LineItem01: Quantity=5, Status=Delivered, Date=09/05/2003
LineItem02: Quantity=5, Status=Shipped, Date=09/07/2003
LineItem03: Quantity=5, Status=Shipped, Date=09/09/2003

So if we were to flatten this like a resultset from a relational join...

Customer LineItem Quantity Status Date
-------- -------- -------- --------- ----------
Alpha 01 20 Delivered 09/21/2003
Alpha 02 40 Shipped 09/23/2003
Beta 01 60 Cancelled 09/24/2003
Charlie 01 5 Delivered 09/05/2003
Charlie 02 5 Shipped 09/07/2003
Charlie 03 5 Shipped 09/09/2003

select * from po,lines where ... order by status, customer, date desc

Which would look like this...

Customer LineItem Quantity Status Date
-------- -------- -------- --------- ----------
Beta 01 60 Cancelled 09/24/2003
Alpha 01 20 Delivered 09/21/2003
Charlie 01 5 Delivered 09/05/2003
Alpha 02 40 Shipped 09/23/2003
Charlie 03 5 Shipped 09/09/2003
Charlie 02 5 Shipped 09/07/2003

I apologize for not having workable examples to being with.
Thanks for your help so far.
 
R

Roedy Green

Is it possible to use a comparator, or other sorting technique, to sort
a collection has fields that are themselves collections, and, use fields
from the nested collection the sort criteria?

You obviously need to write an odd Comparator that fishes the fields
out.

Since a sort often looks at each key more than once, it may pay to
extract the necessary info from the subcollections before sorting.
 
R

Roedy Green

I'd like to sort the POList based on
getCustomerName from the PO object and getDeliveryDate from the many
LineItems objects.

You might like to maintain the delivery date for sort ( e.g. last,
first, lowest, highest ) as a separate field.
 
V

VisionSet

Doug Poland said:
Customer: Alpha
LineItem01: Quantity=20, Status=Delivered, Date=09/21/2003
LineItem02: Quantity=40, Status=Shipped, Date=09/23/2003
Customer: Beta
LineItem01: Quantity=60, Status=Cancelled, Date=09/24/2003
Customer: Charlie
LineItem01: Quantity=5, Status=Delivered, Date=09/05/2003
LineItem02: Quantity=5, Status=Shipped, Date=09/07/2003
LineItem03: Quantity=5, Status=Shipped, Date=09/09/2003

So if we were to flatten this like a resultset from a relational join...

Customer LineItem Quantity Status Date
-------- -------- -------- --------- ----------
Alpha 01 20 Delivered 09/21/2003
Alpha 02 40 Shipped 09/23/2003
Beta 01 60 Cancelled 09/24/2003
Charlie 01 5 Delivered 09/05/2003
Charlie 02 5 Shipped 09/07/2003
Charlie 03 5 Shipped 09/09/2003

select * from po,lines where ... order by status, customer, date desc

Which would look like this...

Customer LineItem Quantity Status Date
-------- -------- -------- --------- ----------
Beta 01 60 Cancelled 09/24/2003
Alpha 01 20 Delivered 09/21/2003
Charlie 01 5 Delivered 09/05/2003
Alpha 02 40 Shipped 09/23/2003
Charlie 03 5 Shipped 09/09/2003
Charlie 02 5 Shipped 09/07/2003

Well won't just running a sort against a relevent comparator do the trick?
Sort both array lists, and you should have what you want.
 
D

Doug Poland

VisionSet said:
Well won't just running a sort against a relevent comparator do
the trick? Sort both array lists, and you should have what you want.
That's what I'm hoping, but I can't figure out how a comparator would
work on the nested collection.

For example, here's a comparator that would sort on POList
Customer Name...


public int compare(Object arg0, Object arg1) {

PurchaseOrders po1 = (PurchaseOrders) arg0;
PurchaseOrders po2 = (PurchaseOrders) arg1;

//
// This compare method sorts on Name
//
return po1.getCustomerName().compareTo(po2.getCustomerName());

}


So how does one sort the nested collection?

public int compare(Object arg0, Object arg1) {

PurchaseOrders po1 = (PurchaseOrders) arg0;
PurchaseOrders po2 = (PurchaseOrders) arg1;
int result = 0;

//
// This compare method sorts on Status ASC, Date DESC, Name ASC
//
Collections.sort(po1.getItemsList(), new ComparePO_Status());
Collections.sort(po2.getItemsList(), new ComparePO_Status());

/* ????
*
* So how do I return an int from this?
* Each sublist is sorted on status, how do I tell the
* comparator to return a -1, 0, or 1?
*/

return result;
}
 
V

VisionSet

Doug Poland said:
That's what I'm hoping, but I can't figure out how a comparator would
work on the nested collection.

For example, here's a comparator that would sort on POList
Customer Name...


public int compare(Object arg0, Object arg1) {

PurchaseOrders po1 = (PurchaseOrders) arg0;
PurchaseOrders po2 = (PurchaseOrders) arg1;

//
// This compare method sorts on Name
//
return po1.getCustomerName().compareTo(po2.getCustomerName());

}


So how does one sort the nested collection?

public int compare(Object arg0, Object arg1) {

PurchaseOrders po1 = (PurchaseOrders) arg0;
PurchaseOrders po2 = (PurchaseOrders) arg1;
int result = 0;

//
// This compare method sorts on Status ASC, Date DESC, Name ASC
//
Collections.sort(po1.getItemsList(), new ComparePO_Status());
Collections.sort(po2.getItemsList(), new ComparePO_Status());

/* ????
*
* So how do I return an int from this?
* Each sublist is sorted on status, how do I tell the
* comparator to return a -1, 0, or 1?
*/

return result;
}

Since you've got this bit:

return po1.getCustomerName().compareTo(po2.getCustomerName());

then obviously the LineItem version is going to be similar.

So just sort it in the same way, the only thing really to decide is when &
where you do it.

Perhaps on addition to the PurchaseOrder? or whenever you've stopped making
additions to the LineItems collection.

ie

class PurchaseOrder {

addLineItems(List items) {
lineItems = items;
Collections.sort(lineItems, new LineItemComparator());
}
}


Sorry, I fail to see any real problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,786
Messages
2,569,626
Members
45,328
Latest member
66Teonna9

Latest Threads

Top