You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Roman Rytov <rr...@entopia.com> on 2002/11/10 19:41:19 UTC

[Collection] Is there a way to branch (group) a collection?

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


Re: [Collection] Is there a way to branch (group) a collection?

Posted by Stephen Colebourne <sc...@btopenworld.com>.
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" <ro...@apache.org>
> 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" <ch...@mindview.net>
> To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
> 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:
<ma...@jakarta.apache.org>
> > For additional commands, e-mail:
<ma...@jakarta.apache.org>
> >
> >
> >
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: [Collection] Is there a way to branch (group) a collection?

Posted by Rob Oxspring <ro...@apache.org>.
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" <ch...@mindview.net>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
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:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>
>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: [Collection] Is there a way to branch (group) a collection?

Posted by Chintan <ch...@mindview.net>.
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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>