I have written my own implementation of java.utils.List. Now I'd like to test it, but I cannot manage to fill my collection with objects since it shows <identifier> expected whenever I add anything :
public static void main(String[] args) {}
MyCollection col = new MyCollection(10);
int[] tab = {1,2,4,5,6};
col.add(tab);
And the whole code here :
http://paste.pocoo.org/show/291343/
EDIT
MyCollection<Integer> col = new MyCollection<Integer>(10);
Integer[] tab = {1,2,4,5,6};
col.add(tab);
still the same :/
You're trying to add an int[] as item of a Collection<Integer> which accepts Integer (or autoboxed int) items only. This would only work if you have a Collection<int[]> (of which the added array would then be the sole item).
To convert an int[] to a Collection<Integer>, you need to loop over it:
int[] array = { 1, 2, 3, 4, 5 };
Collection<Integer> collection = new ArrayList<Integer>();
for (int item : array) {
collection.add(item);
}
See also:
Arrays tutorial
Collections tutorial
Generics tutorial
You're missing your Type. It's a generic class, so it should be something like
MyCollection<Integer> col = new MyCollection<Integer>(10);
Change:
MyCollection<Integer> col = new MyCollection<Interger>(10);
You need to specify the T of your MyCollection.
The generic implications here would not cause an error, you would simply get a warning because any object you add to the list is erased to Object, so you could add any object and would lose type safety.
You have instantiated a list whose members are a single object, whatever the type may be, but you're trying to add an array as a single member. You have a couple of options, but I would stick with:
List<Integer> myCollection = new MyCollection<Integer>(10);
myCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));
If you really intended on have a list of arrays, you would do:
List<Integer[]> myCollection = new MyCollection<Integer[]>(10);
myCollection.add(new Integer[]{1,2,3,4,5,6});
A couple of notes:
Program to the interface (see my example)
Your implementation is called MyCollection, but it's actually an implementation of List, so a name like MyList seems more appropriate unless you plan on actually extending Collection.
I assume this is just an exercise, but I don't see the point in extending List. You know that java.util.ArrayList exists right?
Related
I couldn't really come up with the words as to how to describe my question in the title.
What I'm trying to accomplish is something like this: (Pseudo code)
SuperClass[] superArray = new SuperClass[];
// work on superArray
// ...
SubClass[] subArray = superArray.asAnArrayOfSubClass();
`
Is something like this possible?
You cannot add members : methods or fields to an array. So no, it is not possible :
SubClass[] subArray = superArray.asAnArrayOfSubClass();
To define a behavior for an array, instead create a method where you pass the array :
SubClass[] doThat(SuperClass[] superArray){
....
}
Even if conceptually, a type should not know its subtypes, if it is your requirement it is valid to convert manually an array of a specific type to an array of a subclass of this specific type.
For example, you can have employees stored in an array that at time are promoted as managers. This method could do this conversion :
Manager[] promote(Employee[] employees){
Manager[] managers = new Manager[employees.length];
for (int i=0; i<employees.length; i++){
Employee e = employee[i];
managers[i] = new Manager(....);
}
return managers;
}
No. Not possible. Because not every Parent is a Child. The reverse is possible as Every child is a Parent.
See the below example.
Object[] supers = new Object[5];
Integer[] childs = supers // Errrr.. No I have Strings, Doubles too
But the reverse is possible
Integer[] childs = new Integer[5];
Object[] supers = childs // Ok, I can hold any object.
Casting to subclasses is a code smell, and probably you should reconsider your design. Also try to use a java collection api (Iterable, Collection, List), with generics, and not primitive arrays, which you can subclass adding your own methods like the example below:
public interface IteratorWithIndex<T> extends Iterator<T> {
int index();
}
There are restrictions that your subclass should match super class wrt properties and methods and you are only overriding those.
Below is an example of how you could do this using streams API.
Number[] array = new Number[]{12, 20, 30, 40};
List<Integer> list = Arrays.stream(array)
.map(e -> (Integer) e)
.collect(Collectors.toList());
System.out.println(list.toArray());
This question already has answers here:
I'm getting an error in my Java code but I can't see whats wrong with it. Help?
(5 answers)
Closed 5 years ago.
I created this arrayList:
Double[] arrayOfNumbers = new Double[List.size()];
And I try to add it numbers with this:
arrayOfNumbers.add(0.9);
This gives me an error message that says:
Cannot invoke add(double) on the array type Double[]
So, how can I add that value in this Double[] arraylist?
That is not an ArrayList. That is an array.
You can declare an arraylist of doubles as :
int initialCapacity = 20;
List<Double> doubles = new ArrayList<Double>(initialCapacity);
doubles.add(0.9);
You can add more than 20 values in an ArrayList even though the initial capacity is specified as 20.
But to declare an array and populate it:
double[] doublesArray = new doubles[20];
doubles[0] = 0.9;
doubles[1] = 0.5;
.....
doubles[19] = 0.7; // 19 is the last index for an array of size 20.
If you add more than 20 here, you will get ArrayIndexOutOfBoundsException
Double[] is not ArrayList to add to an array you can use :
Double[] arrayOfNumbers = new Double[List.size()];
arrayOfNumbers[0] = 0.9;
Instead to add to an ArrayList you can use :
List<Double> arrayOfNumbers = new ArrayList<>();
arrayOfNumbers.add(0.9);
Arrays and lists are different things. Arrays don't have an add method, but are assignable by the subscript ([]) operator:
arrayOfNumbers[0] = 0.9;
Double[] arrayOfNumbers = new Double[List.size()] is not a List
it is an array.
We declare arrays with [] and lists with <> and generics.
For example `
int[]arr=new int[3] is an array of 3 ints, but List<Integer>list=new ArrayList<>() is a list of integers(not primitive ints you CANNOTwrite code like this List<int>=new ArrayList<>()
Hope that helps!
java.util.List is a different that an array(which has limited predefined size).
you can't declare/perform as above you did in question, java compiler will complain if you do so.
you are phasing a error like,
Cannot invoke add(double) on the array type Double[]
because an array(arrayOfNumbers) do not having a such method(add) which you can execute on arrayOfNumbers.
However,
general syntax to initialize of an array of any type(here in example, Integer taken FYI) is likewise,
int intArray[] = {1,2,3}; // initialize at the time of creation
or
int arrayOfNumbers [] = new int[] {1, 2, 3};
or
intArray[index] = 1;
Moreover, you can switch from array to List & vice-versa as likewise,
List<Integer> list = java.util.Arrays.asList(arrayOfNumbers);
or
Integer [] intArray = list.toArray(new Integer[list.size()]);
A List is an Interface that extends another interface called Collection, so a List is-a Collection. An Interface defines and describes behavior, it defines a contract that another class must conform to, and one of the classes that does so is called java.util.ArrayList, and add() is one behaviour defined in the List contract, because a List must have the ability for things to be added to it. An ArrayList is one type of a List. What you have created is NOT an ArrayList, it is an Array.
An array is a primitive data structure, once created, it's size cannot be changed, If you wish to add a new element to an array you have to create a new array that is bigger, then transfer all elements from the old array to the new one. Under the covers an ArrayList does exactly that. THIS IS HOW YOU CREATE an ArrayList :
//a list of Objects of type `Double`
List<Double> listOfNumbers = new ArrayList<>();
if you wish to add an element to this list, you would do this :
listOfNumbers.add(5.2);
You do seem like you still need to read a beginners book and practice basic Java programming. I would like to suggest this playlist
This will really be helpful to you, and remember you can only learn something by doing it hands-on, NOT by just watching somebody else doing it.
What it comes down to is I'm attempting to construct a List<T> from the java.util.List package based on an enumerator, but here's the catch- I don't want the first value to be in the list. The way that I've come up with doing this... Well... It can't be a good thing.
Here's the code I'm using:
Arrays.asList(Arrays.asList(MyEnum.values()).remove(0));
This effectively creates a List<> from my enum, and removes the first value, then tries to create another list with the created list.
This may actually be the correct way to do it, but just looking at it is screaming "Inefficient". I showed it to a few people on a forum that I'm a member of and they all said how ugly it was, and laughed; However not a single one of them could/would provide a better way to go about doing it.
I don't think that code is really ugly or inefficient. The bigger problem is it doesn't work because the list returned by Arrays.asList is backed by the underlying array, and so it has a fixed size.
You can use subList instead of remove to get it working:
List<MyEnum> list = Arrays.asList(MyEnum.values());
list = list.subList(1, list.size());
This means that the resulting list actually consists of two list objects (the asList and its subList), which may or may not bother you. However, you can create a flat ArrayList from the resulting list:
list = new ArrayList<>(list);
If you'd rather minimize object allocation, loop the values and add them to a single list directly:
MyEnum[] values = MyEnum.values();
List<MyEnum> list = new ArrayList<>(values.length - 1);
for (int i = 1; i < values.length; i++)
list.add(values[i]);
How about:
Arrays.asList(MyEnum.values()).subList(1, MyEnum.values().length);
Are you sure you can't (wouldn't want to) use MyEnum.values and treat your first element differently where it's used?
public enum Enums {
first,
b,
c,
d,
e,
f;
public boolean isFirst(Enums e) {
return e == first;
}
}
This would work:
List<T> enums = Arrays.asList(Arrays.copyOfRange(MyEnum.values(), 1, MyEnum.values().length - 1));
Or java 8:
Arrays.stream(MyEnum.values()).collect(Collectors.toList()).subList(1, MyEnum.values() - 1);
Hmmm... not much better .
I have an Array of primitives, for example for int, int[] foo. It might be a small sized one, or not.
int foo[] = {1,2,3,4,5,6,7,8,9,0};
What is the best way to create an Iterable<Integer> from it?
Iterable<Integer> fooBar = convert(foo);
Notes:
Please do not answer using loops (unless you can give a good explanation on how the compiler do something smart about them?)
Also note that
int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);
Will not even compile
Type mismatch: cannot convert from List<int[]> to List<Integer>
Also check
Why is an array not assignable to Iterable?
before answering.
Also, if you use some library (e.g., Guava), please explain why this is the Best. ( Because its from Google is not a complete answer :P )
Last, since there seems to be a homework about that, avoid posting homeworkish code.
Integer foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
List<Integer> list = Arrays.asList(foo);
// or
Iterable<Integer> iterable = Arrays.asList(foo);
Though you need to use an Integer array (not an int array) for this to work.
For primitives, you can use guava:
Iterable<Integer> fooBar = Ints.asList(foo);
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
<type>jar</type>
</dependency>
For Java8 with lambdas: (Inspired by Jin Kwon's answer)
final int[] arr = { 1, 2, 3 };
final Iterable<Integer> i1 = () -> Arrays.stream(arr).iterator();
final Iterable<Integer> i2 = () -> IntStream.of(arr).iterator();
final Iterable<Integer> i3 = () -> IntStream.of(arr).boxed().iterator();
just my 2 cents:
final int a[] = {1,2,3};
java.lang.Iterable<Integer> aIterable=new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int pos=0;
public boolean hasNext() {
return a.length>pos;
}
public Integer next() {
return a[pos++];
}
public void remove() {
throw new UnsupportedOperationException("Cannot remove an element of an array.");
}
};
}
};
With Java 8, you can do this.
final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();
Guava provides the adapter you want as Int.asList(). There is an equivalent for each primitive type in the associated class, e.g., Booleans for boolean, etc.
int foo[] = {1,2,3,4,5,6,7,8,9,0};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
The suggestions above to use Arrays.asList won't work, even if they compile because you get an Iterator<int[]> rather than Iterator<Integer>. What happens is that rather than creating a list backed by your array, you created a 1-element list of arrays, containing your array.
In Java 8 or later, Iterable is a functional interface returns Iterator.
So you can do this.
static Iterable<Integer> convert(int[] array) {
return () -> Arrays.stream(array).iterator();
}
and
int[] array = {1, 2, 3};
Iterable<Integer> iterable = convert(array);
for (int i : iterable)
System.out.println(i);
output:
1
2
3
I had the same problem and solved it like this:
final YourType[] yourArray = ...;
return new Iterable<YourType>() {
public Iterator<YourType> iterator() {
return Iterators.forArray(yourArray); // Iterators is a Google guava utility
}
}
The iterator itself is a lazy UnmodifiableIterator but that's exactly what I needed.
First of all, I can only agree that Arrays.asList(T...) is clearly the best solution for Wrapper types or arrays with non-primtive datatypes. This method calls a constructor of a simple private static AbstractList implementation in the Arrays class which basically saves the given array reference as field and simulates a list by overriding the needed methods.
If you can choose between a primtive type or a Wrapper type for your array, I would use the Wrapper type for such situations but of course, it's not always useful or required.
There would be only two possibilities you can do:
1) You can create a class with a static method for each primitive datatype array (boolean, byte, short, int, long, char, float, double returning an Iterable<WrapperType>. These methods would use anonymous classes of Iterator (besides Iterable) which are allowed to contain the reference of the comprising method's argument (for example an int[]) as field in order to implement the methods.
-> This approach is performant and saves you memory (except for the memory of the newly created methods, even though, using Arrays.asList() would take memory in the same way)
2) Since arrays don't have methods (as to be read on the side you linked) they can't provide an Iterator instance either. If you really are too lazy to write new classes, you must use an instance of an already existing class that implements Iterable because there is no other way around than instantiating Iterable or a subtype.
The ONLY way to create an existing Collection derivative implementing Iterable is to use a loop (except you use anonymous classes as described above) or you instantiate an Iterable implementing class whose constructor allows a primtive type array (because Object[] doesn't allow arrays with primitive type elements) but as far as I know, the Java API doesn't feature a class like that.The reason for the loop can be explained easily:for each Collection you need Objects and primtive datatypes aren't objects. Objects are much bigger than primitive types so that they require additional data which must be generated for each element of the primitive type array. That means if two ways of three (using Arrays.asList(T...) or using an existing Collection) require an aggregate of objects, you need to create for each primitive value of your int[] array the wrapper object. The third way would use the array as is and use it in an anonymous class as I think it's preferable due to fast performance.
There is also a third strategy using an Object as argument for the method where you want to use the array or Iterable and it would require type checks to figure out which type the argument has, however I wouldn't recommend it at all as you usually need to consider that the Object hasn't always the required type and that you need seperate code for certain cases.
In conclusion, it's the fault of Java's problematic Generic Type system which doesn't allow to use primitive types as generic type which would save a lot of code by using simply Arrays.asList(T...). So you need to program for each primitive type array, you need, such a method (which basically makes no difference to the memory used by a C++ program which would create for each used type argument a seperate method.
You can use IterableOf from Cactoos:
Iterable<String> names = new IterableOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
Then, you can turn it into a list using ListOf:
List<String> names = new ListOf<>(
new IterableOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
)
);
Or simply this:
List<String> names = new ListOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
While a similar answer has already been sort of posted, I think the reason to use the new PrimitiveIterator.OfInt was not clear. A good solution is to use Java 8 PrimitiveIterator since it's specialized for primitive int types (and avoids the extra boxing/unboxing penalty):
int[] arr = {1,2,3};
// If you use Iterator<Integer> here as type then you can't get the actual benefit of being able to use nextInt() later
PrimitiveIterator.OfInt iterator = Arrays.stream(arr).iterator();
while (iterator.hasNext()) {
System.out.println(iterator.nextInt());
// Use nextInt() instead of next() here to avoid extra boxing penalty
}
Ref: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html
In java8 IntSteam stream can be boxed to stream of Integers.
public static Iterable<Integer> toIterable(int[] ints) {
return IntStream.of(ints).boxed().collect(Collectors.toList());
}
I think performance matters based on the size of the array.
So there's Arrays.asList(T... a) but this works on varargs.
What if I already have the array in a T[] a? Is there a convenience method to create a List<T> out of this, or do I have to do it manually as:
static public <T> List<T> arrayAsList(T[] a)
{
List<T> result = new ArrayList<T>(a.length);
for (T t : a)
result.add(t);
return result;
}
Just because it works with varargs doesn't mean you can't call it normally:
String[] x = { "a", "b", "c" };
List<String> list = Arrays.asList(x);
The only tricky bit is if T is Object, where you should use a cast to tell the compiler whether it should wrap the argument in an array or not:
Object[] x = ...;
List<Object> list = Arrays.asList((Object[]) x);
or
Object[] x = ...;
List<Object[]> list = Arrays.asList((Object) x);
As you probably already know, there is a Static class called java.util.Collections which has a number of useful methods for dealing wit arrays such as searching and sorting.
As for your question, the Collection interface specifies methods to add, remove and toArray, amongst others. For one reason or another, the API's authors decided that the add and addAll method will be the only input functions provided to the user.
One explanation for why Java Lists cannot add arrays of objects is that Lists use an iterator and iterators are more strict in their scrolling (i.e. going to the next value) than Arrays which do not have to have all their index values i=(1, 2, 5, 9, 22, ...).
Also, Arrays are not type safe; that is, they cannot guarantee that all their elements conform to a specific super-class or interface, whereas generics (of which List is a member) can guarantee type safety. Hence, the list has the chance to validate each item using the add method.
I think that you can rest assure that your method of adding an array to a list is one of the most (if not most) efficient way of achieving this effect in Java.