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]>