Question about returning generics

Discussion in 'Java' started by aaronfude@gmail.com, Feb 4, 2007.

  1. Guest

    Hi,

    Suppose I have an array of diverse types and I want extract all
    objects of a certain type (e.g. Date) and return it as a vector of
    that type. Is it possible to write a function that will return arrays
    of different types depending on the input parameters. I guess I have
    just about answered my own question negatively, but I'm hoping for
    something like this:

    Vector<Date> dates = collect(set, Date.class);
    Vector<Double> doubles = collect(set, Double.class);

    Not possible, right?

    Thanks!

    Aaron Fude
     
    , Feb 4, 2007
    #1
    1. Advertising

  2. Tom Hawtin Guest

    wrote:
    >
    > Suppose I have an array of diverse types and I want extract all
    > objects of a certain type (e.g. Date) and return it as a vector of
    > that type. Is it possible to write a function that will return arrays
    > of different types depending on the input parameters. I guess I have
    > just about answered my own question negatively, but I'm hoping for
    > something like this:
    >
    > Vector<Date> dates = collect(set, Date.class);
    > Vector<Double> doubles = collect(set, Double.class);


    Arrays or Vectors.

    > Not possible, right?


    I don't see why it should be impossible.

    public static <T> List<T> collect(
    Iterable<?> items, Class<? extends T> target
    ) {
    if (target.isPrimitive()) {
    throw new IllegalArgumentException();
    }
    List<T> found = new java.util.ArrayList<T>();
    for (Object item : items) {
    if (target.isInstance(item)) {
    found.add(item);
    }
    }
    return found;
    }

    @SuppressWarnings("unchecked")
    public static <T> T[] collect(
    Iterable<?> items, Class<T> target
    ) {
    List<T> found = collect(items, target);
    return found.toArray((T[])
    java.lang.reflect.Arrays.newInstance(target, found.size())
    );
    }

    [Disclaimer: Not tested, or even compiled.]

    I am not, however, convinced that this is a brilliant design.

    Tom Hawtin
     
    Tom Hawtin, Feb 4, 2007
    #2
    1. Advertising

  3. <> wrote in message
    news:...
    > Hi,
    >
    > Suppose I have an array of diverse types and I want extract all
    > objects of a certain type (e.g. Date) and return it as a vector of
    > that type. Is it possible to write a function that will return arrays
    > of different types depending on the input parameters. I guess I have
    > just about answered my own question negatively, but I'm hoping for
    > something like this:
    >
    > Vector<Date> dates = collect(set, Date.class);
    > Vector<Double> doubles = collect(set, Double.class);
    >



    You want something like

    static <T> Vector<T> collect(Collection c, Class<T> clazz)
    {
    Vector<T> v = new Vector<T>();
    for (Object o : c)
    {
    if (clazz.isInstance(o))
    v.add((T) o);
    }
    return v;
    }

    Class<T> is an idiom worth learning. The only member (other than null) of
    the type Class<T> is T.class. If you're writing generic code and will need
    access to the Class object for a parameterized type, having an argument of
    type Class<T> is the way to get it.

    Warning: I've compiled this but not tested it, so beware of subtle bugs.
    Note also that isInstance() returns false for null arguments (like
    instanceof does), so you'll never see null members in the Vector.
     
    Mike Schilling, Feb 4, 2007
    #3
  4. Chris Uppal Guest

    wrote:

    > Suppose I have an array of diverse types and I want extract all
    > objects of a certain type (e.g. Date) and return it as a vector of
    > that type. Is it possible to write a function that will return arrays
    > of different types depending on the input parameters.


    Probably not a good idea to design your API in terms of raw arrays, nor to use
    Vector (essentially obsolete, and has been for many years). But using
    java.util.List it seems to work OK:

    -- chris

    ======== Utils.java ============
    import java.util.*;

    public class Utils
    {
    public static <X>
    List<X>
    collect(List<Object> list, Class<X> clobj, boolean allowNull)
    {
    List<X> filtered = new ArrayList<X>();
    for (Object elem : list)
    {
    if (allowNull && elem == null)
    filtered.add(null);
    else if (clobj.isInstance(elem))
    filtered.add(clobj.cast(elem));
    }
    return filtered;
    }
    }
    ======== Test.java ============
    import java.util.*;

    public class Test
    {
    public static void
    main(String[] args)
    {
    List<Object> all = Arrays.asList(new Object[] {
    "one",
    null,
    true,
    false,
    'c',
    88.88,
    100
    });

    System.out.println("Strings (or null):");
    List<String> strings = Utils.collect(all, String.class, true);
    for (String s : strings)
    System.out.println("\t" + s);

    System.out.println("Numbers:");
    List<Number> numbers = Utils.collect(all, Number.class, false);
    for (Number n : numbers)
    System.out.println("\t" + n);
    }
    }
    =============================
     
    Chris Uppal, Feb 4, 2007
    #4
  5. Chris Uppal Guest

    I wrote:

    > public static <X>
    > List<X>
    > collect(List<Object> list, Class<X> clobj, boolean allowNull)
    > {


    Come to think of it (and influenced in part by Tom's post), I think that:

    public static <Super, Sub extends Super>
    List<Sub>
    collect(
    List<? extends Super> list,
    Class<Sub> clobj,
    boolean allowNull)
    {
    List<Sub> filtered = new ArrayList<Sub>();
    for (Super elem : list)
    {
    if (allowNull && elem == null)
    filtered.add(null);
    else if (clobj.isInstance(elem))
    filtered.add(clobj.cast(elem));
    }
    return filtered;
    }

    is to be prefered.

    Notice how the attempt to satisfy the compiler results in reams of code, no
    real gain, and a distraction of attention from /non/ inessentials such as the
    hardwired decision that the returned List as an ArrayList.

    -- chris
     
    Chris Uppal, Feb 4, 2007
    #5
  6. Tom Hawtin Guest

    Chris Uppal wrote:
    > I wrote:
    >
    >> public static <X>
    >> List<X>
    >> collect(List<Object> list, Class<X> clobj, boolean allowNull)
    >> {

    >
    > Come to think of it (and influenced in part by Tom's post), I think that:
    >
    > public static <Super, Sub extends Super>
    > List<Sub>
    > collect(
    > List<? extends Super> list,
    > Class<Sub> clobj,
    > boolean allowNull)
    > {


    > is to be prefered.


    I certainly wouldn't want to insist on a List of Object. I'm not sure
    what the point of 'Super' is there. Most code will not specify type
    arguments for generic methods explicitly (wish the same was true for
    types in constructors). Object will always be sufficient for 'Super'.

    I don't like the allowNull parameter. I don't see what the point of
    using it would be. The code would be simpler without it. And the calling
    code would be more understandable without a strange boolean flag tagged
    onto the end without explanation.

    Also generic parameters. Can we have them in AOL? I spent ages the other
    day trying to find where a pair of classes/interfaces were defined.
    NetBeans just shrugged. Then I realised what they were. (OTOH, I
    sometimes like multiple characters - EXC for exceptions and THIS for
    self type).

    > Notice how the attempt to satisfy the compiler results in reams of code, no
    > real gain, and a distraction of attention from /non/ inessentials such as the
    > hardwired decision that the returned List as an ArrayList.


    Yes, but at least it is the method author who has to worry about it. And
    hopefully the method will be used more often than it is implemented. A
    programmer using the method doesn't need to concern his or herself about
    it. Just see that it has been worked out, and the compiler will note any
    misunderstanding.

    Tom Hawtin
     
    Tom Hawtin, Feb 4, 2007
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Juergen Berchtel
    Replies:
    1
    Views:
    6,038
    John C. Bollinger
    May 20, 2005
  2. sks
    Replies:
    2
    Views:
    402
    Ingo R. Homann
    Aug 29, 2005
  3. Replies:
    3
    Views:
    1,744
    Roedy Green
    Sep 17, 2005
  4. Replies:
    11
    Views:
    682
    Christos Georgiou
    May 2, 2006
  5. Soul
    Replies:
    0
    Views:
    535
Loading...

Share This Page