Trying to create and test a comparable arraylist class - java

Here's the code I have. I'm trying to test out my bubbleSort Method..
import java.util.ArrayList;
import java.util.List;
public class MyArrayList<T extends Comparable<? super T>> extends ArrayList<Comparable<T>> {
private static final long serialVersionUID = 1L;
private MyArrayList<T> myList; // class list
public MyArrayList(ArrayList<Comparable<T>> asList) {
for (Comparable<T> e: asList) {
myList.add(e);
}
}
public void bubbleSort() {
boolean swapped = true;
while (swapped) {
swapped = false;
for (int i = 0; i < this.size() - 1; i++) {
if (this.get(i).compareTo((T) this.get(i + 1)) > 0) {
swapped = true;
Comparable<T> temp = this.get(i);
this.set(i, this.get(i + 1));
this.set(i + 1, temp);
}
}
}
}
}
In my test class, I am having trouble creating lists to test my bubbleSort method. I want to try to create an Integer list (from an array), a String list, and a few others, but I keep getting various errors.
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
public class MyArrayListTest<T> {
public void setUp() {
Integer[] testIntArray = new Integer[]{0, 1, 2, 3};
MyArrayList<Integer> myList = new MyArrayList<Integer>(Arrays.asList(testIntArray));
}
}
Any ideas why this doesn't work, and how I would go about creating a MyArrayList?

You should change your constructor from:
public MyArrayList(ArrayList<Comparable<T>> asList)
to:
public MyArrayList(List<T> asList)
Arrays.asList doesn't return a java.util.ArrayList, which is why new MyArrayList<Integer>(Arrays.asList(testIntArray)) doesn't compile. Arrays.asList returns an instance of a nested class defined inside the Arrays class, which is also called ArrayList, but more importantly, the return type of Arrays.asList(T... a) is List<T>.

Several problems here.
First, once you declared the base type of the list to be comparable, you shouldn't be using Comparable<T> anymore. This is actually what breaks your constructor. It expects a list of Comparable of something, and gets a list of Integer. Although an Integer is a Comparable, a List<Integer> is not a List<Comparator>. These are two different types.
Second, as you were told, the method Arrays.asList() returns a List and that's not assignment-compatible to ArrayList without type casting (and will fail on type casting, because it's not a java.util.ArrayList).
So the declaration of your constructor should actually be
public MyArrayList(List<T> asList)
And your loop variable e should also be declared as T. The basic fact is that Java already knows that T extends Comparable so it knows it has a compareTo() method.
But you also have a logical error which you have not ran into so far because of the constructor declaration. You actually have two collections in a MyArrayList. One is the field myList, and the other is this. Since you are extending an ArrayList, this is an ArrayList.
In your constructor, you add data to myList. But in your sort method, you are comparing and swapping the data in this! This means that it will probably attempt to sort an empty list, as you didn't fill it up in the constructor (unless you call its add method from your main).
In fact, adding information to myList will probably throw a NullPointerException as you did not initialize myList and you have no way of doing so as it is a MyArrayList, and has only the List-based constructor, which, if you will use, will send you on an infinite loop and end up with a Stack Overflow.
The list itself should probably extend ArrayList<T> rather than ArrayList<Comparable<T>>. Again, T is already known to extend Comparable. And then you could declare the temp variable T rather than Comparable<T>. It should also be unnecessary to cast the argument to T as it will already be T, being the base type of this.

Related

How to create generic array of class with two type parameter and constrain? [duplicate]

Due to the implementation of Java generics, you can't have code like this:
public class GenSet<E> {
private E a[];
public GenSet() {
a = new E[INITIAL_ARRAY_LENGTH]; // error: generic array creation
}
}
How can I implement this while maintaining type safety?
I saw a solution on the Java forums that goes like this:
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
But I really don't get what's going on.
I have to ask a question in return: is your GenSet "checked" or "unchecked"?
What does that mean?
Checked: strong typing. GenSet knows explicitly what type of objects it contains (i.e. its constructor was explicitly called with a Class<E> argument, and methods will throw an exception when they are passed arguments that are not of type E. See Collections.checkedCollection.
-> in that case, you should write:
public class GenSet<E> {
private E[] a;
public GenSet(Class<E> c, int s) {
// Use Array native method to create array
// of a type only known at run time
#SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, s);
this.a = a;
}
E get(int i) {
return a[i];
}
}
Unchecked: weak typing. No type checking is actually done on any of the objects passed as argument.
-> in that case, you should write
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
a = new Object[s];
}
E get(int i) {
#SuppressWarnings("unchecked")
final E e = (E) a[i];
return e;
}
}
Note that the component type of the array should be the erasure of the type parameter:
public class GenSet<E extends Foo> { // E has an upper bound of Foo
private Foo[] a; // E erases to Foo, so use Foo[]
public GenSet(int s) {
a = new Foo[s];
}
...
}
All of this results from a known, and deliberate, weakness of generics in Java: it was implemented using erasure, so "generic" classes don't know what type argument they were created with at run time, and therefore can not provide type-safety unless some explicit mechanism (type-checking) is implemented.
You can do this:
E[] arr = (E[])new Object[INITIAL_ARRAY_LENGTH];
This is one of the suggested ways of implementing a generic collection in Effective Java; Item 26. No type errors, no need to cast the array repeatedly. However this triggers a warning because it is potentially dangerous, and should be used with caution. As detailed in the comments, this Object[] is now masquerading as our E[] type, and can cause unexpected errors or ClassCastExceptions if used unsafely.
As a rule of thumb, this behavior is safe as long as the cast array is used internally (e.g. to back a data structure), and not returned or exposed to client code. Should you need to return an array of a generic type to other code, the reflection Array class you mention is the right way to go.
Worth mentioning that wherever possible, you'll have a much happier time working with Lists rather than arrays if you're using generics. Certainly sometimes you don't have a choice, but using the collections framework is far more robust.
Here's how to use generics to get an array of precisely the type you’re looking for while preserving type safety (as opposed to the other answers, which will either give you back an Object array or result in warnings at compile time):
import java.lang.reflect.Array;
public class GenSet<E> {
private E[] a;
public GenSet(Class<E[]> clazz, int length) {
a = clazz.cast(Array.newInstance(clazz.getComponentType(), length));
}
public static void main(String[] args) {
GenSet<String> foo = new GenSet<String>(String[].class, 1);
String[] bar = foo.a;
foo.a[0] = "xyzzy";
String baz = foo.a[0];
}
}
That compiles without warnings, and as you can see in main, for whatever type you declare an instance of GenSet as, you can assign a to an array of that type, and you can assign an element from a to a variable of that type, meaning that the array and the values in the array are of the correct type.
It works by using class literals as runtime type tokens, as discussed in the Java Tutorials. Class literals are treated by the compiler as instances of java.lang.Class. To use one, simply follow the name of a class with .class. So, String.class acts as a Class object representing the class String. This also works for interfaces, enums, any-dimensional arrays (e.g. String[].class), primitives (e.g. int.class), and the keyword void (i.e. void.class).
Class itself is generic (declared as Class<T>, where T stands for the type that the Class object is representing), meaning that the type of String.class is Class<String>.
So, whenever you call the constructor for GenSet, you pass in a class literal for the first argument representing an array of the GenSet instance's declared type (e.g. String[].class for GenSet<String>). Note that you won't be able to get an array of primitives, since primitives can't be used for type variables.
Inside the constructor, calling the method cast returns the passed Object argument cast to the class represented by the Class object on which the method was called. Calling the static method newInstance in java.lang.reflect.Array returns as an Object an array of the type represented by the Class object passed as the first argument and of the length specified by the int passed as the second argument. Calling the method getComponentType returns a Class object representing the component type of the array represented by the Class object on which the method was called (e.g. String.class for String[].class, null if the Class object doesn't represent an array).
That last sentence isn't entirely accurate. Calling String[].class.getComponentType() returns a Class object representing the class String, but its type is Class<?>, not Class<String>, which is why you can't do something like the following.
String foo = String[].class.getComponentType().cast("bar"); // won't compile
Same goes for every method in Class that returns a Class object.
Regarding Joachim Sauer's comment on this answer (I don't have enough reputation to comment on it myself), the example using the cast to T[] will result in a warning because the compiler can't guarantee type safety in that case.
Edit regarding Ingo's comments:
public static <T> T[] newArray(Class<T[]> type, int size) {
return type.cast(Array.newInstance(type.getComponentType(), size));
}
This is the only answer that is type safe
E[] a;
a = newArray(size);
#SafeVarargs
static <E> E[] newArray(int length, E... array)
{
return Arrays.copyOf(array, length);
}
To extend to more dimensions, just add []'s and dimension parameters to newInstance() (T is a type parameter, cls is a Class<T>, d1 through d5 are integers):
T[] array = (T[])Array.newInstance(cls, d1);
T[][] array = (T[][])Array.newInstance(cls, d1, d2);
T[][][] array = (T[][][])Array.newInstance(cls, d1, d2, d3);
T[][][][] array = (T[][][][])Array.newInstance(cls, d1, d2, d3, d4);
T[][][][][] array = (T[][][][][])Array.newInstance(cls, d1, d2, d3, d4, d5);
See Array.newInstance() for details.
In Java 8, we can do a kind of generic array creation using a lambda or method reference. This is similar to the reflective approach (which passes a Class), but here we aren't using reflection.
#FunctionalInterface
interface ArraySupplier<E> {
E[] get(int length);
}
class GenericSet<E> {
private final ArraySupplier<E> supplier;
private E[] array;
GenericSet(ArraySupplier<E> supplier) {
this.supplier = supplier;
this.array = supplier.get(10);
}
public static void main(String[] args) {
GenericSet<String> ofString =
new GenericSet<>(String[]::new);
GenericSet<Double> ofDouble =
new GenericSet<>(Double[]::new);
}
}
For example, this is used by <A> A[] Stream.toArray(IntFunction<A[]>).
This could also be done pre-Java 8 using anonymous classes but it's more cumbersome.
You do not need to pass the Class argument to the constructor.
Try this.
public class GenSet<T> {
private final T[] array;
#SafeVarargs
public GenSet(int capacity, T... dummy) {
if (dummy.length > 0)
throw new IllegalArgumentException(
"Do not provide values for dummy argument.");
this.array = Arrays.copyOf(dummy, capacity);
}
#Override
public String toString() {
return "GenSet of " + array.getClass().getComponentType().getName()
+ "[" + array.length + "]";
}
}
and
GenSet<Integer> intSet = new GenSet<>(3);
System.out.println(intSet);
System.out.println(new GenSet<String>(2));
result:
GenSet of java.lang.Integer[3]
GenSet of java.lang.String[2]
This is covered in Chapter 5 (Generics) of Effective Java, 2nd Edition, item 25...Prefer lists to arrays
Your code will work, although it will generate an unchecked warning (which you could suppress with the following annotation:
#SuppressWarnings({"unchecked"})
However, it would probably be better to use a List instead of an Array.
There's an interesting discussion of this bug/feature on the OpenJDK project site.
Java generics work by checking types at compile time and inserting appropriate casts, but erasing the types in the compiled files. This makes generic libraries usable by code which doesn't understand generics (which was a deliberate design decision) but which means you can't normally find out what the type is at run time.
The public Stack(Class<T> clazz,int capacity) constructor requires you to pass a Class object at run time, which means class information is available at runtime to code that needs it. And the Class<T> form means that the compiler will check that the Class object you pass is precisely the Class object for type T. Not a subclass of T, not a superclass of T, but precisely T.
This then means that you can create an array object of the appropriate type in your constructor, which means that the type of the objects you store in your collection will have their types checked at the point they are added to the collection.
Although the thread is dead, I would like to draw your attention to this.
Generics are used for type checking during compile time. Therefore, the purpose is to check
What comes in is what you need.
What you return is what the consumer needs.
Check this:
Don't worry about typecasting warnings when you are writing a generic class; worry when you are using it.
What about this solution?
#SafeVarargs
public static <T> T[] toGenericArray(T ... elems) {
return elems;
}
It works and looks too simple to be true. Is there any drawback?
The example is using Java reflection to create an array. Doing this is generally not recommended, since it isn't typesafe. Instead, what you should do is just use an internal List, and avoid the array at all.
Look also to this code:
public static <T> T[] toArray(final List<T> obj) {
if (obj == null || obj.isEmpty()) {
return null;
}
final T t = obj.get(0);
final T[] res = (T[]) Array.newInstance(t.getClass(), obj.size());
for (int i = 0; i < obj.size(); i++) {
res[i] = obj.get(i);
}
return res;
}
It converts a list of any kind of object to an array of the same type.
I have found a quick and easy way that works for me. Note that i have only used this on Java JDK 8. I don't know if it will work with previous versions.
Although we cannot instantiate a generic array of a specific type parameter, we can pass an already created array to a generic class constructor.
class GenArray <T> {
private T theArray[]; // reference array
// ...
GenArray(T[] arr) {
theArray = arr;
}
// Do whatever with the array...
}
Now in main we can create the array like so:
class GenArrayDemo {
public static void main(String[] args) {
int size = 10; // array size
// Here we can instantiate the array of the type we want, say Character (no primitive types allowed in generics)
Character[] ar = new Character[size];
GenArray<Character> = new Character<>(ar); // create the generic Array
// ...
}
}
For more flexibility with your arrays you can use a linked list eg. the ArrayList and other methods found in the Java.util.ArrayList class.
Passing a list of values...
public <T> T[] array(T... values) {
return values;
}
I made this code snippet to reflectively instantiate a class which is passed for a simple automated test utility.
Object attributeValue = null;
try {
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
else if(!clazz.isInterface()){
attributeValue = BeanUtils.instantiateClass(clazz);
}
} catch (Exception e) {
logger.debug("Cannot instanciate \"{}\"", new Object[]{clazz});
}
Note this segment:
if(clazz.isArray()){
Class<?> arrayType = clazz.getComponentType();
attributeValue = Array.newInstance(arrayType, 0);
}
for array initiating where Array.newInstance(class of array, size of array). Class can be both primitive (int.class) and object (Integer.class).
BeanUtils is part of Spring.
The forced cast suggested by other people did not work for me, throwing an exception of illegal casting.
However, this implicit cast worked fine:
Item<K>[] array = new Item[SIZE];
where Item is a class I defined containing the member:
private K value;
This way you get an array of type K (if the item only has the value) or any generic type you want defined in the class Item.
Actually an easier way to do so, is to create an array of objects and cast it to your desired type like the following example:
T[] array = (T[])new Object[SIZE];
where SIZE is a constant and T is a type identifier
No one else has answered the question of what is going on in the example you posted.
import java.lang.reflect.Array;
class Stack<T> {
public Stack(Class<T> clazz, int capacity) {
array = (T[])Array.newInstance(clazz, capacity);
}
private final T[] array;
}
As others have said generics are "erased" during compilation. So at runtime an instance of a generic doesn't know what its component type is. The reason for this is historical, Sun wanted to add generics without breaking the existing interface (both source and binary).
Arrays on the other hand do know their component type at runtime.
This example works around the problem by having the code that calls the constructor (which does know the type) pass a parameter telling the class the required type.
So the application would construct the class with something like
Stack<foo> = new Stack<foo>(foo.class,50)
and the constructor now knows (at runtime) what the component type is and can use that information to construct the array through the reflection API.
Array.newInstance(clazz, capacity);
Finally we have a type cast because the compiler has no way of knowing that the array returned by Array#newInstance() is the correct type (even though we know).
This style is a bit ugly but it can sometimes be the least bad solution to creating generic types that do need to know their component type at runtime for whatever reason (creating arrays, or creating instances of their component type, etc.).
I found a sort of a work around to this problem.
The line below throws generic array creation error
List<Person>[] personLists=new ArrayList<Person>()[10];
However if I encapsulate List<Person> in a separate class, it works.
import java.util.ArrayList;
import java.util.List;
public class PersonList {
List<Person> people;
public PersonList()
{
people=new ArrayList<Person>();
}
}
You can expose people in the class PersonList thru a getter. The line below will give you an array, that has a List<Person> in every element. In other words array of List<Person>.
PersonList[] personLists=new PersonList[10];
I needed something like this in some code I was working on and this is what I did to get it to work. So far no problems.
Generic array creation is disallowed in java but you can do it like
class Stack<T> {
private final T[] array;
public Stack(int capacity) {
array = (T[]) new Object[capacity];
}
}
According to vnportnoy the syntax
GenSet<Integer> intSet[] = new GenSet[3];
creates an array of null references, to be filled as
for (int i = 0; i < 3; i++)
{
intSet[i] = new GenSet<Integer>();
}
which is type safe.
You could create an Object array and cast it to E everywhere. Yeah, it's not very clean way to do it but it should at least work.
try this.
private int m = 0;
private int n = 0;
private Element<T>[][] elements = null;
public MatrixData(int m, int n)
{
this.m = m;
this.n = n;
this.elements = new Element[m][n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
this.elements[i][j] = new Element<T>();
}
}
}
An easy, albeit messy workaround to this would be to nest a second "holder" class inside of your main class, and use it to hold your data.
public class Whatever<Thing>{
private class Holder<OtherThing>{
OtherThing thing;
}
public Holder<Thing>[] arrayOfHolders = new Holder<Thing>[10]
}
Maybe unrelated to this question but while I was getting the "generic array creation" error for using
Tuple<Long,String>[] tupleArray = new Tuple<Long,String>[10];
I find out the following works (and worked for me) with #SuppressWarnings({"unchecked"}):
Tuple<Long, String>[] tupleArray = new Tuple[10];
I'm wondering if this code would create an effective generic array?
public T [] createArray(int desiredSize){
ArrayList<T> builder = new ArrayList<T>();
for(int x=0;x<desiredSize;x++){
builder.add(null);
}
return builder.toArray(zeroArray());
}
//zeroArray should, in theory, create a zero-sized array of T
//when it is not given any parameters.
private T [] zeroArray(T... i){
return i;
}
Edit: Perhaps an alternate way of creating such an array, if the size you required was known and small, would be to simply feed the required number of "null"s into the zeroArray command?
Though obviously this isn't as versatile as using the createArray code.
You could use a cast:
public class GenSet<Item> {
private Item[] a;
public GenSet(int s) {
a = (Item[]) new Object[s];
}
}
I actually found a pretty unique solution to bypass the inability to initiate a generic array. What you have to do is create a class that takes in the generic variable T like so:
class GenericInvoker <T> {
T variable;
public GenericInvoker(T variable){
this.variable = variable;
}
}
and then in your array class just have it start like so:
GenericInvoker<T>[] array;
public MyArray(){
array = new GenericInvoker[];
}
starting a new Generic Invoker[] will cause an issue with unchecked but there shouldn't actually be any issues.
To get from the array you should call the array[i].variable like so:
public T get(int index){
return array[index].variable;
}
The rest, such as resizing the array can be done with Arrays.copyOf() like so:
public void resize(int newSize){
array = Arrays.copyOf(array, newSize);
}
And the add function can be added like so:
public boolean add(T element){
// the variable size below is equal to how many times the add function has been called
// and is used to keep track of where to put the next variable in the array
arrays[size] = new GenericInvoker(element);
size++;
}
If you really want to wrap a generic array of fixed size you will have a method to add data to that array, hence you can initialize properly the array there doing something like this:
import java.lang.reflect.Array;
class Stack<T> {
private T[] array = null;
private final int capacity = 10; // fixed or pass it in the constructor
private int pos = 0;
public void push(T value) {
if (value == null)
throw new IllegalArgumentException("Stack does not accept nulls");
if (array == null)
array = (T[]) Array.newInstance(value.getClass(), capacity);
// put logic: e.g.
if(pos == capacity)
throw new IllegalStateException("push on full stack");
array[pos++] = value;
}
public T pop() throws IllegalStateException {
if (pos == 0)
throw new IllegalStateException("pop on empty stack");
return array[--pos];
}
}
in this case you use a java.lang.reflect.Array.newInstance to create the array, and it will not be an Object[], but a real T[].
You should not worry of it not being final, since it is managed inside your class.
Note that you need a non null object on the push() to be able to get the type to use, so I added a check on the data you push and throw an exception there.
Still this is somewhat pointless: you store data via push and it is the signature of the method that guarantees only T elements will enter. So it is more or less irrelevant that the array is Object[] or T[].

Generic array of complex types

for performance reasons I need to use arrays to store data. I implemented this in a generic fashion like this (see this answer):
import java.lang.reflect.Array;
public class SimpleArray<T> {
private T[] data;
#SuppressWarnings("unchecked")
public SimpleArray(Class<T> cls, int size) {
this.data = (T[]) Array.newInstance(cls, size);
}
public T get(int i) {
return data[i];
}
}
The problem is that I need the involved Class<?>es. However, I might have a more complex class hierarchy containing generics:
public class Outer<T> {
public class Inner {
}
}
I would like to initialize the array as I would with an ordinary class:
SimpleArray<Integer> intArray = new SimpleArray<>(Integer.class, 10);
intArray.get(0);
SimpleArray<Outer<Integer>> outerArray;
// how to initialize this?
SimpleArray<Outer<String>.Inner> innerArray;
// how to initialize this?
I read the post on how to (not) get the Class of something generic (here) but the bottom-line seems to be that everything is type-safety related syntactic sugar.
My question is the following: How can I create instances of the SimpleArray classes above while avoiding as much ugliness as possible?
There are two issues here.
Do you really need to pass in a Class? In this case, no. Your class does not actually need to know the element type at runtime to do its job. For example, you can just do:
public class SimpleArray<T> {
private Object[] data;
public SimpleArray(int size) {
this.data = new Object[size];
}
#SuppressWarnings("unchecked")
public T get(int i) {
return (T)data[i];
}
}
If you really needed a Class<T>, how would you get one? Well, first you need to ask yourself, what are you going to use this for? There will never be a "true" Class<T> for a non-reifiable type T because with a Class<T> you can do things like .isInstance() to check whether something is an instance of T at runtime; but of course it's not possible to check instance-of with non-reifiable types at runtime.
In this case, you're only going to pass it to Array.newInstance(), and Array.newInstance() uses the raw type anyway (it does not care about the compile-time type of the Class parameter -- the parameter type is Class<?> -- it only uses the runtime value of the Class object), it is sufficient to simply coerce a Class object representing the raw type to the appropriately-parameterized Class type:
(Class<Outer<Integer>>)(Class<?>)Outer.class
You seem to be trying to make a class that wraps an array and provides a method to get elements. The class Arrays.ArrayList does exactly that already, so there is no need to reinvent the wheel. It works as follows:
List<String> list = Arrays.asList(new String[30]);
list.set(3, "foo");
System.out.println(list.get(3));
You can't use Arrays.asList to produce a List<T> if the type T is generic without suppressing a warning because it is not possible to create a generic array. You can write a helper method to do this for you though.
#SuppressWarnings("unchecked")
public static <T> List<T> newArray(int size) {
return (List<T>) Arrays.asList(new Object[size]);
}
You can use the returned List to get and set elements without having to cast, even if the type T is generic. For example:
List<List<String>> list = newArray(30);
list.set(4, Arrays.asList("A", "B", "C"));
System.out.println(list.get(4));

Is it better to use generics or Object type for a static helper class in Java?

I was writing a program the other day that required me to: get the frequency of a particular object inside an ArrayList<String>, remove all occurrences of a given item, etc., etc. not specified by the List interface. I decided to write my own helper class and wanted to make it as reusable as possible. I decided to specify List as the parameter type of the collection so I could use it for any class implementing the List interface. But these classes are usually defined using generics, and I did not know what class type the item to be removed would be. So I either had to define the static helper methods generically since a static class can not contain generic types explicitly, or define the class type of the object to be removed as Object. I implemented it in both ways, see below, but am wondering if there any benefits to using one over the other.
Some further questions on the topic:
Why am I able to work around the reference of a generic type in a static context by defining it in the method header rather than the class header?
When using this static method, why do I not have to declare the class Type in its usage? i.e. ListTools_V2.getFrequencyOf(ArrayList<String> items, String s) still works.
Implementation using Object class type
import java.util.List;
/** General utility class for performing frequently needed operations
on any class implementing the List interface **/
public class ListTools {
public static void removeAllOccurrences(List items, Object o) {
while(items.contains(o)) {
items.remove(o);
}
}
public static int getFrequencyOf(List items, Object o) {
int frequency = 0;
for(Object item : items) {
if(item.equals(o)) {
frequency++;
}
}
return frequency;
}
}
Implementation using generics
import java.util.List;
/** General utility class for performing frequently needed operations
on any class implementing the List interface. This implementation
uses generics to maximize reusability. **/
public class ListTools_V2 {
public static <E> void removeAllOccurrences(List<E> items, E o) {
while(items.contains(o)) {
items.remove(o);
}
}
public static <E> int getFrequencyOf(List<E> items,E o) {
int frequency = 0;
for(E item : items) {
if(item.equals(o)) {
frequency++;
}
}
return frequency;
}
}
Both operations operate on equality (.equals()) between the given object reference and the elements inside the list, and equality is not limited to objects of the same type, so you shouldn't restrict o to be the same type as the type parameter of the list.
However, raw types are bad, so you shouldn't use the raw type List. You should parameterize it with a wildcard when there is no need to constrain the type variable against anything:
public static void removeAllOccurrences(List<?> items, Object o)
public static int getFrequencyOf(List<?> items, Object o)
Generic is better as it detects type related issues at compile time.
During runtime "erasure" takes place and there is no "meaning" to generics.
For example:
List apples = new ArrayList();
apples.add(new Apple());
apples.add(new Mango()); //compiles, but this is wrong
apples.add(new Chair()); //compiles, but this is wrong
You must of course be aware of all kinds of "pitfalls" of the generic mechanism.
Examples I can easily think of are:
List<Mango> does not extend List<Fruit> , so you should use List<? super Fruit> or List<? extends Fruit>
You cannot do something like :
T.getClassName()
Generics is the recommended way of implementing such classes. They can be used to give some implicit information to your user (whoever uses this class).
For example:
List<Cat> cats = ...;
ListTools.removeAllOccurrences(cats, new Dog());
it is meaningless since, there cannot be any dogs inside a List of Cats. But user can execute this code and imagine that he has deleted some dogs from the List of cats.On the other hand generic version informs the user about this inappropriate call.
List<Cat> cats = ...;
ListTools_V2.removeAllOccurrences(cats, new Dog()); // Compile time error because it is pointless
Additionally there is a performance gain as well. If the List of Cats contains thousands of Cats, do you really want to search for that Dog inside a large number of Cat List? (contains method actually search the entire List) or do you simply want to avoid it at the compile time? ;)
your getFrequencyOf() method body is essentially same in both the cases except in one case you are passing raw List and in another you are parameterizing it to accept any type.
1-
public static int getFrequencyOf(List items, Object o) {
int frequency = 0;
for(Object item : items) {
if(item.equals(o)) {
frequency++;
}
}
return frequency;
}
Here you List is a raw type. References to generic type List should be parameterized which, is not. But it is open for any type of List (Integer, Long, String etc.)
2-
public static <E> int getFrequencyOf(List<E> items,E o) {
int frequency = 0;
for(E item : items) {
if(item.equals(o)) {
frequency++;
}
}
return frequency;
}
Here you List is NOT a raw type. References to generic type List should be parameterized which, it is. And this as well is open for any type of List (Integer, Long, String etc.)

Java Array list stack

This is the top portion of my ArrayListStack class. I am trying to make values become an array list of T of 10. I am getting an error "incompatible types required: ArrayListStack found:java.util.ArrayList". In the line values = new ArrayList(10)". How would i properly set this value thanks
import java.util.ArrayList;
public class ArrayListStack<T> implements StackInterface<T>
{
private ArrayListStack<Integer> values= new ArrayListStack<Integer>();
private int size;
public ArrayListStack()
{
size = 0;
values = new ArrayList<T>(10);
}
I think you are attempting to use an ArrayList to back your ArrayListStack. It makes no sense for an ArrayListStack to contain another ArrayListStack. If this were to compile, each new ArrayListStack would create another ArrayListStack, which would create another ArrayListStack, etc.
Change the type of your values to ArrayList, and use your T generic type parameter:
private ArrayList<T> values;
No need to initialize it here; you are initializing it in the constructor.
There are multiple errors here:
you declare values as an ArrayListStack while it should be an ArrayList
you declare values by specifying the type parameter to Integer while it should stay T
you initialize values outside the constructor to inizialize it again inside the constructor
you try to initialize values to a different type, with a different type parameter
It should be
private ArrayList<T> values;
ArrayStackList() {
value = new ArrayList<T>(10);
}
You are assigning a generic type to an array list of Integer objects. Furthermore you are already initializing the list in your class definition.
public class ArrayListStack<T> implements StackInterface<T>
{
private ArrayList<T> values; // <-- Note change here
private int size;
public ArrayListStack()
{
size = 0;
values = new ArrayList<T>(10);
}
}
You need to have the same type and generic type for values when you construct it and when you declare it. T is your generic type (a generic generic type, if you will). I also removed the superfluous initialization at the field declaration, since you're re-constructing it in the constructor.
If you're trying to make a class that combines the functionality of ArrayList and StackInterface, make the following changes. Otherwise your code doesn't seem to make much sense
import java.util.ArrayList;
public class ArrayListStack<T> extends ArrayList<T> implements StackInterface<T>
{
public ArrayListStack()
{
//You can set this to whatever initial size you like,
//however if you look at the source code of ArrayList
//you'll discover that 10 is the default size of an ArrayList
super(10);
}
//Add whatever methods are required by StackInterface
}
In this situation, you can seamlessly use your class as both a standard ArrayList and a StackInterface

Is there a parameter I can use in Java that works with all for-each loops?

Suppose I've got a method that accepts an array and processes each element in it using Java's built in for-each loop, like this:
public static void myFun(SomeClass[] arr) {
for (SomeClass sc : arr) {
// Stuff is processed here
}
}
This works just fine, but now I want to be able to pass the same method a List<SomeClass> instead. Am I destined to use Collection.toArray(T []), or is there a parameter I can use for myFun() that accepts any type that can be used in a for-each construct?
To clarify: I want a method signature that will accept any iterable object, be it a primitive array or a Collection. I can very easily write two methods, with one wrapping the other, but I'm just curious if there's a better way.
I would suggest using Iterable, Collection or List as the parameter type.
IMO, collections should be preferred to reference arrays. If you happen to have an array Arrays.asList does the conversion nicely. Arrays.asList allows gets and sets back through to the array, but obviously not "structural" modifications which would change the array length.
myFun(Arrays.asList(arr));
You may have to use wildcards in extreme/general cases.
public static void myFun(Iterable<? extends SomeClass> somethings) {
for (SomeClass something : somethings) {
// something is processed here
}
}
It is noteworthy that Collections.toArray and Arrays.asList work slightly differently. asList keeps the original array to back the collection, so changes to the collection will be reflected in the array. Collections.toArray makes a (shallow) copy of the collection data. Making a copy is often what you would want anyway if you are returning an array. Asymmetrically, if you are passing as an argument you generally do not copy (unless storing as a field).
Use Iterable. That's what it's for.
As you said, Iterable won't handle arrays.
You don't want to use multiple methods wrapping each other. That rules out Arrays.asList and Collection.toArray.
So the answer to your question is no, there isn't a way. But if you can use Lists, why would you ever use arrays?
I would still go with Iterable here. I like it better than Collection because in the past I've had classes that implemented Iterable but were not collections; this made it easy for them to lazily retrieve values as needed, and I could use the foreach loop on them.
you cannot, java Arrays doesn't implements Iterable:
public static int sum(Iterable<Integer> elements) {
int s = 0;
for (int i : elements) {
s += i;
}
return s;
}
public static void main(String[] args) {
L1: System.out.println(sum(1,2,3));
L2: System.out.println(sum(Arrays.asList(1,2,3)));
L3: System.out.println(sum(new int[] { 1,2,3 }));
}
this results in two compile-time errors in (L1 and L3); so you must design your
method to accept an Iterable (Collections) and/or an Array, at least one method must perform some conversion (to/from array)
WORKAROUND:
you may be try with an adapter:
public class ArrayIterator<T> implements Iterator<T> {
private final T[] array;
private int i;
public ArrayIterator(T[] anArray) {
array = anArray;
i = 0;
}
public boolean hasNext() {
return i < array.length;
}
public T next() {
return array[i++];
}
public void remove() {
throw new UnsupportedOperationException();
}
}
private static int sum(final Integer ... elements) {
return sum(new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new ArrayIterator<Integer>(elements);
}
});
}
you should pay attention only when dealing with primitive arrays; when you use only
reference object (your case) ArrayIterator + anonymous class are cool
hope it helps
Short answer: no, there's no single method signature that type-safely accepts both an Iterable and an array. Obviously you could just accept Object, but that would be a hack as well.
Long-ish answer: Since the enhanced for-loop is effectively defined twice (once for arrays and once for Iterable), you'll need to provide two overloaded methods as well:
public static void myFun(SomeClass[] array) {
for (SomeClass sc : array) {
doTheProcessing(sc);
}
}
public static void myFun(Iterable<? extends SomeClass> iterable) {
for (SomeClass sc : iterable) {
doTheProcessing(sc);
}
}
Although the source of the two methods looks exactly the same, you'll need to define it twice (unless of course you wrap the Array in your own Iterable as #dfa outlined).
There's a little know feature of Java Generics in Java 1.5+ where you can use <? extends Subtype> in your method calls and constructors. You could use <? extends Object>, and then anything that deals with those would have access only to methods on Object. What you might really want is something more like this:
List<? extends MyCrustaceans> seaLife = new ArrayList<? extends MyCrustaceans>();
MyShrimp s = new MyShrimp("bubba");
seaLife.add(s);
DoStuff(seaLife);
...
public static void DoStuff(List<? extends MyCrustaceans> seaLife)
{
for (MyCrustaceans c : seaLife) {
System.out.println(c);
}
}
So if you have a base class (like MyCrustaceans), you can use any methods of that base class in DoStuff (or of the Object class, if your parameter is <? extends Object>). There's a similar feature of <? super MyType>, where it accepts a parameter that is a supertype of the given type, instead of a subtype. There's some restrictions on what you can use "extends" and "super" for in this fashion. Here's a good place to find more info.
public static void myFun(Collection<MyClass> collection) {
for (MyClass mc : collection) {
// Stuff is processed here
}
}

Categories

Resources