问题描述:

Quick Question...

Can collections in Java hold more than one type? Or do they all have to be the same type?

thanks

网友答案:

Simple answer

Yes.

More detailed answer

You can either use generic collection, without <T> value, for example:

ArrayList a = new ArrayList();
a.add(2);
a.add("String");

Using collections without <T> is a bad habit and most IDEs / compilers give a warning here. You can circumvent it by using a collection of Object, i.e.:

ArrayList<Object> a = new ArrayList<Object>();

Or you can find some common interface or supertype that these element must have in, for example ArrayList<Number> - and you can store various objects that have common Number superclass, i.e. BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short:

ArrayList<Number> a = new ArrayList<Number>();
a.add(2); // integer
a.add(42L); // long
a.add(123.45d); // double
System.out.println(a.toString()); // => [2, 42, 123.45]

Note that it essentially means that a elements are of Number class — i.e. you can't ask to execute subclass-specific methods (for example, Double#isInfinite(), which doesn't exist in Number superclass), although you can typecast in run-time if you somehow know it's safe to typecast:

a.get(2).isInfinite()          // compile-time error
((Double) a.get(2)).isInfinite() // => false
((Double) a.get(1)).isInfinite() // run-time error (ClassCastException)

Run-time typecasting is also generally frowned upon, as it effectively circumvents proper compile-time type safety.

Also note that it's impossible to assign (or use) ArrayList<Number> in place of ArrayList<Integer> and vice-versa, i.e. this will fail to compile:

public void printNumbers(ArrayList<Number> list) {
    list.forEach(System.out::println);
}
ArrayList<Integer> a = new ArrayList<Integer>();
printNumbers(a); // "incompatible types"

as well as this:

public void printIntegers(ArrayList<Integer> list) {
    list.forEach(System.out::println);
}
ArrayList<Number> a = new ArrayList<Number>();
printIntegers(a); // "incompatible types"

To declare a variable to be able to accept both ArrayList<Number> or any of its subclasses, one can use ArrayList<? extends Number> or ArrayList<? super Number> syntax. extends is generally used when you're going to consume (i.e. read) from the object in your method, super is used when you're going to produce (i.e. write). Given that printout is consuming, it's safe to use extends:

public void printNumbers(ArrayList<? extends Number> list) {
    list.forEach(System.out::println);
}

ArrayList<Integer> listInt = new ArrayList<Integer>();
printNumbers(listInt); // works
ArrayList<Double> listDbl = new ArrayList<Double>();
printNumbers(listDbl); // also works

There is a good answer in Difference between <? super T> and <? extends T> in Java for more in-depth explanation.

网友答案:

If you want them to hold any more than one type, use Collection<Object>. However, you won't know what you're getting without doing some if (x instanceof MyType) calls, which are rather inefficient.

网友答案:

They have to be of the same Supertype. So if you have objects of type A, then a Collection<A> can store objects of type A and of every subtype of A.

If you want to allow arbitrary types, then use Collection<Object>, otherwise take the most general appropriate super-class.

However, you will then have to manually cast from the most general type (Object) to the specific type you have in mind. You can use the typeof operator to find out what the type is.

网友答案:

Every Collection classes can contains heterogeneous objects except TreeSet and TreeMap. Since TreeSet and TreeMap stores elements according to some sorting order. so, if objects are of different type it will not be able to sort it because comparison between the objects will not be possible for sorting.

网友答案:

Yes they can but they should not (that's why generics have been put in place since 5th version of jdk) in general store different types, as this is the straight way to errors.

网友答案:

I believe you can also use Collection<?>.

网友答案:

The question is why you want to do that? Then retrieving and manipulating them would not be easy.

网友答案:

Yes collections in java can hold more than one type as below. But it will throw an exception if done using the following way.

    ArrayList al = new ArrayList();
    al.add(1);
    al.add("name");
    al.add(1.2f);

    Iterator itr =al.iterator();
    while(itr.hasNext())
    {
        System.out.println(itr.next());
    }

Hence it's better to mention the type that you're using. To get rid of the exception the above program can be modified as below.

    ArrayList<Integer> al = new ArrayList<Integer>();
    al.add(1);
    al.add(2);
    al.add(3);

    Iterator itr =al.iterator();
    while(itr.hasNext())
    {
        System.out.println(itr.next());
    }

    ArrayList<String> al1 = new ArrayList<String>();
    al1.add("Words");
    al1.add("Names");
    al1.add("Characters");

    Iterator itr1 =al1.iterator();
    while(itr1.hasNext())
    {
        System.out.println(itr1.next());
    }

You can also use more than these types.

相关阅读:
Top