For this particular example the idea suits just fine! I like it. The
problem occurs when you need to group a collection on an aggregate
condition. Let's say the Man class has also a City attribute and you
wanna group the men by age AND city. The solution would be to create a
special class CityAgeCopmarator extending the Man class and overriding
equals() and hashCode() methods. As a workaround it's OK but as a
suggested usage of the API is it OK? It looks like not the best approach
from performance point of view.

Roman


> -----Original Message-----
> From: Stephen Colebourne [mailto:[EMAIL PROTECTED]] 
> Sent: Monday, November 25, 2002 12:21 AM
> To: Jakarta Commons Developers List
> Cc: Roman Rytov
> Subject: Re: [Collection] Is there a way to branch (group) a 
> collection?
> 
> 
> Having just worked on it this afternoon, I've realised that 
> the ideal class exists - MultiHashMap.
> 
> MultiHashMap holds a list of elements for each key, exactly 
> as you describe:
> 
> MultiMap multi = new MultiHashMap();
> Man[] men = ...
> for (int i =0; i < men.length; i++) {
>  multi.put(men[i].age, men[i]);
> }
> 
> After looping through all the men, the MultiMap will contain 
> a key for each age. Each key will hold a list of the Man 
> objects. Thus using the data from the email below: 
> multi.get(new Integer(35)  ==> {('Isac', 35) , ('Gonsales', 
> 35)}, multi.get(new Integer(32)  ==> {('Jerry', 32) , 
> ('Hans', 32) , ('Mussa', 32)}, multi.get(new Integer(22)  ==> 
> {('Moshe' , 22)}
> 
> This seems to solve the problem.
> Stephen
> 
> ----- Original Message -----
> From: "Rob Oxspring" <[EMAIL PROTECTED]>
> > How about adding a method to CollectionUtils along the lines of the
> following:
> >
> > public static Collection group(Collection source, 
> Transformer grouper){
> >     Map groups = new HashMap();
> >     Iterator i = source.iterator();
> >     while(i.hasNext()){
> >         Object value = i.next();
> >         Object key = grouper.transform(value);
> >         Collection group = (Collection)groups.get(key);
> >         if(group==null){
> >             group = new ArrayList();
> >             groups.put(key,group);
> >         }
> >         group.add(value);
> >     }
> >     return groups.values();
> > }
> >
> > and then using a transformer along the lines of:
> >
> > class AgeGrouper implements Transformer{
> >     public Object transform(Object input){
> >         Man man = (Man)input;
> >         return String.valueOf(man.age);
> >     }
> > }
> >
> > then CollectionUtils.group(source, ageGrouper) should produce 
> > something
> like:
> > {
> > {('Isac', 35) , ('Gonsales', 35)},
> > {('Jerry', 32) , ('Hans', 32) , ('Mussa', 32)},
> > {('Moshe' , 22)}
> > }
> >
> > This seems to solve the required problem in a single pass, although 
> > the
> number of map lookups might offset this?  It's a pattern I
> > find myself repeating lots, except that I normally return the map 
> > rather
> than just values and I allow an optional Map parameter so
> > that a TreeMap can be used on occasions (also allows using a non 
> > ArrayList
> for each group iff you know the group keys in advance).
> >
> > Should I send a patch?
> >
> > Rob
> >
> > ----- Original Message -----
> > From: "Chintan" <[EMAIL PROTECTED]>
> > To: "Jakarta Commons Developers List" 
> <[EMAIL PROTECTED]>
> > Sent: Sunday, November 10, 2002 10:03 PM
> > Subject: Re: [Collection] Is there a way to branch (group) a 
> > collection?
> >
> >
> > > I am not aware of any direct functionality but 
> > > Collection.retainAll()
> can be used to the grouping.
> > >
> > > public interface Predicate {
> > >   public boolean evaluate(Object obj);
> > > }
> > >
> > > class Man {
> > >   private int age;
> > >   private String name;
> > >   private Predicate predicate; //Strategy.
> > >
> > >   public Man(int a, String n){
> > >     this.age = a;
> > >     this.name = n;
> > >   }
> > >
> > >   //override equals
> > >   public boolean equals(Object obj) {
> > >     if(predicate != null)
> > >       return predicate.evaluate(obj);
> > >     else
> > >       //Override equals here.
> > >       //Do normal comparison
> > >   }
> > >   public static Collection grouped(Collection sourceCollection,
> > >       Predicate p, Man type) {
> > >     predicate = p;
> > >     return sourceCollection.retainAll(new ArrayList().add(type));
> > >   }
> > > }
> > >
> > > public class FindPredicate{
> > >   public static void main(String[] args){
> > >     ArrayList men = new ArrayList();
> > >     for(int i = 0 ;i < 30; i++)
> > >       men.add(new Man("Name: " + 1, i);
> > >     //From the above collection get all men with age 25
> > >     System.out.println(Man.grouped(men, new Predicate() {
> > >       public boolean evaluate(Object obj) {
> > >         //Compare ages.
> > >         if(age == (Man)obj.age) return true;
> > >         return false;
> > >       }
> > >     }, new Man("", 25));
> > >   }
> > > }
> > >
> > >
> > >
> > > Roman Rytov wrote:
> > >
> > > >Assume a collection of objects exists and there is an object 
> > > >implementing Predicate interface. Also let's say that 
> > > >evaluate(Object
> > > >obj) method returns a number of distinct objects (out of this
> > > >collection) and the number is noticeably less than total 
> amount of
> > > >objects in the collection. Is there a way to get all collections
> grouped
> > > >by the predicator? An example may be schematically written like:
> > > >
> > > >class Man {
> > > >String name;
> > > >int age;
> > > >}
> > > >
> > > >class AgePredicator implements Predicate {
> > > >    int age;
> > > >    boolean evaluate (Object obj) {
> > > >Man man = (Man)obj;
> > > >return man.age == this.age;
> > > >}
> > > >
> > > >
> > > >collection men = { ('Isac', 35), ('Jerry', 32), 
> ('Gonsales', 35), 
> > > >('Moshe' , 22), ('Hans', 32), ('Mussa', 32)}
> > > >
> > > >afer grouping it's supposed to get 3 collections:
> > > >
> > > >('Isac', 35), ('Gonsales', 35),
> > > >('Jerry', 32), ('Hans', 32), ('Mussa', 32)}
> > > >('Moshe' , 22),
> > > >
> > > >
> > > >Do we have something in the API do achieve it easily?
> > > >
> > > >
> > > >_______________________
> > > >Roman Rytov
> > > >
> > > >
> > > >
> > > >
> > >
> > >
> > > --
> > > To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> > > For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
> > >
> > >
> > >
> >
> >
> > --
> > To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> > For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
> >
> 
> 

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to