I am new to Groovy and, despite reading many articles and questions about this, I am still not clear of what is going on.
From what I understood so far, when you create a new array in Groovy, the underlying type is a Java ArrayList. This means that it should be resizable, you should be able to initialize it as empty and then dynamically add elements through the add method, like so:
MyType[] list = []
list.add(new MyType(...))
This compiles, however it fails at runtime: No signature of method: [LMyType;.add() is applicable for argument types: (MyType) values: [MyType#383bfa16]
What is the proper way or the proper type to do this?
The Groovy way to do this is
def list = []
list << new MyType(...)
which creates a list and uses the overloaded leftShift operator to append an item
See the Groovy docs on Lists for lots of examples.
What you actually created with:
MyType[] list = []
Was fixed size array (not list) with size of 0. You can create fixed size array of size for example 4 with:
MyType[] array = new MyType[4]
But there's no add method of course.
If you create list with def it's something like creating this instance with Object (You can read more about def here). And [] creates empty ArrayList in this case.
So using def list = [] you can then append new items with add() method of ArrayList
list.add(new MyType())
Or more groovy way with overloaded left shift operator:
list << new MyType()
Related
I start learning the Java generic collection using Deitel Harvey book - but I am facing a difficulty understanding the three line of codes below - Do all of them perform the same operation on by intializing and adding the relevant values of array ( colors ) to the LinkList variable (list1). How does the second method and third method works - I am having a bit difficulty understanding how Arrays can viewed as a list.. As I know arrays are not dynamic data structure, they have fixed sized length, adding/ removing elements on array can not be done on running time comparing to Lists in general.
String[] colors = { "black", "white", "blue", "cyan" };
List< String > list1 = new LinkedList< String >();
// method 1 of initalizing and adding elments to the list
for (String color : colors)
list1.add(color);
// method 2 of initializing and adding elements to the list
List< String > list1 = new LinkedList< String > (Arrays.asList(colors));
// method 3 of initializing and adding elements to the list
List< String > list1 = Arrays.asList(colors);
Please help me understand my queries above, don't judge me as I am still new to this.
Thank you, Sinan
Actually knowledge of generics is not necessary for answering this question.
As you correctly identifier arrays are static in the sense that you can't add elements to them or remove them.
Lists, however, usually allow those operations.
The List returned by Arrays.asList() does have the add/remove methods (otherwise it would not be a valid List). However actually calling those methods will throw an UnsupportedOperationException exactly because you can't actually add elements to an array (for which this List is simply a view/wrapper).
Operations that don't structurally modify the list (i.e. that don't change the number of elements in the list) are entirely possible: set(int, E) works just fine on the List returned by Arrays.asList().
Arrays.asList returns a fixed-size list backed by the specified array.
It is actually a bridge between Array and Collection framework. But returned list write through to the array.
Only your first method does anything to the LinkedList you have initially assigned into list1. The other two assign a new, unrelated list to it. The third option assigns something that isn't a LinkedList, but a special implementation of the List interface backed by your String array. In the third case you won't be able to add/remove elements from the list, but you can iterate over it and update existing slots. Basically, it does what a plain array does, just through the List interface.
Arrays.asList creates a List from an Array. Arrays in general can't be viewed as lists in Java. They can only be wrapped in a list.
So method 2 is used to have a specific list implementation LinkedList in this case.
to Method 2, just check the Api here:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/LinkedList.html#LinkedList(java.util.Collection)
For sure, Lists implement the Collections Interface so this Constructor will work here.
to Method 3, just check out the Api here: http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#asList(T...)
Every time you are interested in implementation you can look into certain method. For example, by press Ctrl+left mouse button onto method or class.
// method 2 of initializing and adding elements to the list
List<String> list1 = new LinkedList<String> (Arrays.asList(colors));
This code leads to:
List<String> list1 = new LinkedList<String> (new ArrayList<String>(colors));
In constructor of ArrayList:
ArrayList(E[] array) {
if (array==null)
throw new NullPointerException();
a = array;
}
the actual array is copied to encapsulated private array field(link is copied).
Then in constructor of LinkedList:
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
Every element of passed collection is added to the LinkedList.
if you see the link below
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/LinkedList.html#LinkedList%28java.util.Collection%29
you will see the constructor of linked list class which is accepting a collection object as parameter.
Any in your post, the 2nd and 3 rd lines are passing an object of collection class(i.e Arrays.asList is finally giving a List which is a sub class of collection).
So both 2nd and 3rd lines fairly valid implementations.
More over you can observe one more good coding practice in all the 3 lines.
That is
writing code to interceptors than to classes
. (referring
LinkedList
instance with
List
interface)
Always try to refer your classes with interceptors which is a good practice
I have an array
String[] path={abc,bcd};
I pass this array in a method:
addElement(path);
In method
void addElement(String[] path)
{
// here i got value suppose "qsd" and i want to add it after "bcd" ie 2 index of array
path[path.lenght]="qsd";
}
But this is giving me an error.
I dont want to use an ArrayList.
The biggest problem is that arrays in Java are not trivially resizable. What you wind up doing instead is actually creating a new array, and adding each of the elements to that. This will be slower than the ArrayList code, and uglier as well.
This also means that any code which points to the old array will no longer work. If you only have one instance, you could have addElement return the new array like so
String[] addElement(String old[]){
String arr[] = new String[old.length+1];
//copy all the elements in old...
arr[old.length] = "whatever";
return arr;
}
Then use
path = addElement(path);
You should use ArrayList
Otherwise you have to resize the array by allocating new memory of the size of the original array +1, copy the elements from the old one to the new one, and add in the new element.
You can't change the size of emulated array in GWT (even if javascript arrays support this stuff). You'll have always to create a new instance of array. Most common way to solve this problem is to use one of the collection classes (like java.util.ArrayList) . Example:
ArrayList<String> path = new ArrayList<String>(Arrays.asList("abc","bbc"));
path.add("qsd");
I would like to create an array of ArrayList<String>. I tried the following:
static ArrayList<String>[] displayBlocks = new ArrayList<String>[3];
However, I'm getting a compile time error:
generic array creation
I have added import java.util.*;. How can I get it to compile?
if you want an array of arraylist:
import java.util.ArrayList;
import java.util.List;
public class Foo{
List [] arrayOfLists = new ArrayList[10];
}
Here is a related post. you cant create a generic array of arraylist.
You can do this:
import java.util.ArrayList;
import java.util.List;
public class Foo{
ArrayList<ArrayList<String>> ll = new ArrayList<ArrayList<String>>();
}
This construct is indeed not allowed in Java. You could use the varargs hack:
static List<String>[] displayBlocks = createArray(3);
with
public static <E> E[] createArray(int length, E... elements) {
return Arrays.copyOf(elements, length);
}
Needless to say, a List<List<String>> is better, unless you're extremely tight on memory, but then I'd wonder why you don't use a String[][].
A side from the other answer one can also create the list like this, which might feel a little bit more familiar
static ArrayList<String>[] displayBlocks = (ArrayList<String>[]) new ArrayList[3];
From the Java Language Specification section on array creation expressions:
It is a compile-time error if the ClassOrInterfaceType does not denote a reifiable type (ยง4.7). . . . The rules above imply that the element type in an array creation expression cannot be a parameterized type, other than an unbounded wildcard.
Like others have said, use an ArrayList of ArrayLists, or else use a cast (where you might want to also suppress unchecked conversion warnings).
What you are doing wrong :
You have not created an object. Remember that in java
1) All objects have constructors.
2) Constructors are methods.
3) To create an object, you must call the constructor , thus, you are calling a method !
Your desire is ambiguous . But it will be good to read both of these answers :
1) You could make an Array of array lists : This is a data structure with 10 array lists. it is essentially a 2D array where the amount of columns per row is variable, but there will only be 10 rows.
This would be an odd data structure to create. It might represent, for example, a domain model where you have exactly 10 people and each of those people had a variable number of dvds in their dvd collection. so you would have 10 rows, each one with an array list in it.
static ArrayList[] displayBlocks = new ArrayList[10];
not that there is no () here, just a [] * This is because we havent populated our array, rather, we just declare that there is an array with 10 slots, and each slot will have type "ArrayList". To populate, you would have to iterate and add displayBlock[0]=new ArrayList(), for 0-9.
2) Probably, you just wanted a simple array list , which is a linear collection of items.
To do this you would simply declare :
Collection a = new ArrayList();
//or
List a = new ArrayList();
Now ... you should ask yourself why you can declare the variable as either a Collection or a List, if you want to really java's collections work.
What would be the syntax to create a LinkedList<Object[]>[] type variable?
I have tried:
public LinkedList<Object[]>[] myList = new LinkedList<Object[]>()[];
but this doesn't work.
In Java you can't create generic arrays. You can however do this with ArrayList class or any class that implements the List interface.
List<LinkedList<Object[]>> myList = new ArrayList<LinkedList<Object[]>>();
The declaration LinkedList<Object[]>[] means an array of lists of arrays - is that the intention?
Assuming that it is, you create it with the syntax for creating arrays:
public LinkedList<Object[]>[] myArray = new LinkedList[ARRAY_SIZE];
This creates an array of the specified size (ARRAY_SIZE), each cell of which is null.
Note that:
Since you can't create generic arrays in Java, as Hunter McMillen noticed, the right part omits the type of the LinkedList (i.e. "<Object[]>").
I took the liberty of renaming the variable from myList to myArray, since it's an array and not a list.
It's usually a good idea to use the interface (List) and not a specific implementation (LinkedList), unless you need to use methods specific to LinkedList.
So the line would look like this:
public List<Object[]>[] myArray = new List[ARRAY_SIZE];
This question already has answers here:
Create ArrayList from array
(42 answers)
Initialization of an ArrayList in one line
(34 answers)
Closed 6 years ago.
I am aware that you can initialize an array during instantiation as follows:
String[] names = new String[] {"Ryan", "Julie", "Bob"};
Is there a way to do the same thing with an ArrayList? Or must I add the contents individually with array.add()?
Arrays.asList can help here:
new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
Yes.
new ArrayList<String>(){{
add("A");
add("B");
}}
What this is actually doing is creating a class derived from ArrayList<String> (the outer set of braces do this) and then declare a static initialiser (the inner set of braces). This is actually an inner class of the containing class, and so it'll have an implicit this pointer. Not a problem unless you want to serialise it, or you're expecting the outer class to be garbage collected.
I understand that Java 7 will provide additional language constructs to do precisely what you want.
EDIT: recent Java versions provide more usable functions for creating such collections, and are worth investigating over the above (provided at a time prior to these versions)
Here is the closest you can get:
ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));
You can go even simpler with:
List<String> list = Arrays.asList("Ryan", "Julie", "Bob")
Looking at the source for Arrays.asList, it constructs an ArrayList, but by default is cast to List. So you could do this (but not reliably for new JDKs):
ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")
Arrays.asList("Ryan", "Julie", "Bob");
Well, in Java there's no literal syntax for lists, so you have to do .add().
If you have a lot of elements, it's a bit verbose, but you could either:
use Groovy or something like that
use Arrays.asList(array)
2 would look something like:
String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));
This results in some unnecessary object creation though.
The selected answer is: ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));
However, its important to understand the selected answer internally copies the elements several times before creating the final array, and that there is a way to reduce some of that redundancy.
Lets start by understanding what is going on:
First, the elements are copied into the Arrays.ArrayList<T> created by the static factory Arrays.asList(T...).
This does not the produce the same class as java.lang.ArrayListdespite having the same simple class name. It does not implement methods like remove(int) despite having a List interface. If you call those methods it will throw an UnspportedMethodException. But if all you need is a fixed-sized list, you can stop here.
Next the Arrays.ArrayList<T> constructed in #1 gets passed to the constructor ArrayList<>(Collection<T>) where the collection.toArray() method is called to clone it.
public ArrayList(Collection<? extends E> collection) {
......
Object[] a = collection.toArray();
}
Next the constructor decides whether to adopt the cloned array, or copy it again to remove the subclass type. Since Arrays.asList(T...) internally uses an array of type T, the very same one we passed as the parameter, the constructor always rejects using the clone unless T is a pure Object. (E.g. String, Integer, etc all get copied again, because they extend Object).
if (a.getClass() != Object[].class) {
//Arrays.asList(T...) is always true here
//when T subclasses object
Object[] newArray = new Object[a.length];
System.arraycopy(a, 0, newArray, 0, a.length);
a = newArray;
}
array = a;
size = a.length;
Thus, our data was copied 3x just to explicitly initialize the ArrayList. We could get it down to 2x if we force Arrays.AsList(T...) to construct an Object[] array, so that ArrayList can later adopt it, which can be done as follows:
(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));
Or maybe just adding the elements after creation might still be the most efficient.
How about this one.
ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");
This is how it is done using the fluent interface of the op4j Java library (1.1. was released Dec '10) :-
List<String> names = Op.onListFor("Ryan", "Julie", "Bob").get();
It's a very cool library that saves you a tonne of time.