I wrote this code with a String array:
public static String[] prgmNameList = {"bbbbb", "aaaaa"};
My question is now, how can I add a new item to that array like this:
prgmNameList.add("cccc");
prgmNameList is an array. The size of an array object cannot be changed once it has been created. If you want a variable size container, use collections. For example, use an ArrayList :
List<String> prgmNameList = new ArrayList<String>(3);
prgmNameList.add("bbbb");
That said, if you insist on using an array, you will need to copy your initial array into a new array for each new element that you want to add to the array which can be expensive. See System#arrayCopy for more details. In fact, the ArrayList class internally uses an array that is expanded once it is full using System.arrayCopy so why reinvent the wheel? Just use an ArrayList
On simpler terms, note these following points:
Array size is always fixed.(In your example you fixed the array size to 2 by adding 2 elements)
Arrays operate based on index starting from '0' zero, like - prgmNameList[0] will return 1st element added in the array
Array size cannot be changed at any point of time. If you need size to be variable, choose one of List implementations
ArrayList is the best option for your need that can define itself as an 'Array that can shrink or grow'
Sample code:
public static List<String> prgmNameList= new ArrayList<String>();
prgmNameList.add("bbb");
prgmNameList.add("bbb");
prgmNameList.add("ccc");
prgmNameList.remove("bbb"); //Removes by object resolved by equals() method
prgmNameList.remove(2); //Removes by index
You have created an Array which can not grow as it's fixed in size.
You need to create a list in order to add new elements as shown below.
List<String> prgmNameList = new ArrayList<String>();
prgmNameList.add("aaaa");
prgmNameList.add("bbbb");
prgmNameList.add("cccc");
You have to use ArrayList like that
ArrayList<String> al = new ArrayList<>();
// add elements to the array list
al.add("C");
al.add("A");
al.add("E");
al.add("B");
if you want to use array as you did you have to know the number of elements that you want to add
String[] myList = new String[10];
and then
myList[4]="AA"
--
this is not possible to add to myList.
I explain you how ArrayList works and then you will understand.
ArrayList is an class that contains Array from objects. every time you add it check if it have place to store the data in the array if not it creates new array bigger and store the data.
So ArrayList this is the solution (or any other list)
if you want to add to myList you will have to implement arratList..
The method you are looking for is defined for a Collection, but you are using an array with an array initializer.
I suggest switching to the List:
public static List<String> prgmNameList= new ArrayList<>(Arrays.asList("bbbbb","aaaaa"))
Then you can call add on it because now it is a list.
Btw.: Try to prevent having mutable variables in static variables.
So I want to use an arraylist combined with an array, essentially a 2d array list but with the first level as an array list and the second level as an array.
I know that arraylists or arrays can be used as 2d alone, but my first set of data I don't know the size, whereas the second set I know the size to be 30
To give an example the array list should contain names something like
{"bob", "dave", "pete", "alan"}
and then for each name I want to attach an array of size 30, if I was using just arrays I imagine it'd be something like
String[][] array = new String[?][30]();
and then I'd add the names using something like
array[0] = "bob";
and then add data using
array[0][0] = 1;
but I want the first one to be an arraylist
Sorry if this isn't clear, feel free to ask for more explanation
There are several possible approaches.
1) If you don't care about the order of the items, you could use a Map<String, String[]>, with the names ("bob") as keys, and the arrays of length 30 as the values.
2) You could have two separate ArrayLists - one for the names, and one for the arrays. The downside of this is that you have to be careful to update them together.
List<String> names;
List<String[]> values;
3) You could create an Entry class that contains a name and a values array, then store these Entry objects in an ArrayList.
class Entry {
String name;
String[] values;
// etc
}
...
List<Entry> entries = new ArrayList<Entry>(); //etc
Quick overview of our assignment:
User needs to enter grades received. We do not know how many grades user needs to enter. If the user enters "-1" thats when we know the user is done entering grades.
Problem is how do you use a counter and assign values to an array in the same loop? I would rather not have to ask the user to enter all values twice (Once to get array size and the second time to assign grades to index positions).
Our professor gave us a handout that tells us to basically guess the size of the array and hope for the best. I refuse to believe that's the only solution.
Any help would be appreciated. Thanks.
You can't make dynamic array in java.
For that you will have to use List or ArrayList.
We will have to provide the size of array before application run or at coding time, while arrayList gives us facility to add data while we need it, so it's size will automatically increased when we add data.
Example :
import java.util.*;
public class ArrayListDemo {
public static void main(String args[]) {
// create an array list
ArrayList al = new ArrayList();
System.out.println("Initial size of al: " + al.size());
// add elements to the array list
al.add("C");
al.add("A");
al.add("E");
al.add("B");
al.add("D");
al.add("F");
al.add(1, "A2");
System.out.println("Size of al after additions: " + al.size());
// display the array list
System.out.println("Contents of al: " + al);
// Remove elements from the array list
al.remove("F");
al.remove(2);
System.out.println("Size of al after deletions: " + al.size());
System.out.println("Contents of al: " + al);
}
}
this example is from here.
UPDATE :
When you define your list as:
List myList = new ArrayList();
you can only call methods and reference members that belong to List class. If you define it as:
ArrayList myList = new ArrayList();
you'll be able to invoke ArrayList specific methods and use ArrayList specific members in addition to those inherited from List.
List is not a class it is an interface. It doesn't have any methods implemented. So if you call a method on a List reference, you in fact calling the method of ArrayList in both cases.
Using some kind of List is a better choice, as it basically does what you want (can grow and shrink), in fact, ArrayList is just that, a dynamic array.
You can hand roll your own if you can't use a List using System.arraycopy
For example, this will grow or shrink an array to match the size you provide...
public String[] updateArray(String[] src, int size) {
String[] dest = new String[size];
if (size > src.length) {
System.arraycopy(src, 0, dest, 0, src.length);
} else {
System.arraycopy(src, 0, dest, 0, size);
}
return dest;
}
Again... List is easier...
Building a dynamic array involves these basic steps:
-Create an array of a fixed capacity.
-When the size of the array (# of elements added) approach the capacity, create a new array (usually doubling the capacity), and copy all the old elements to the new array.
A linked list is the most efficient for your task of building the array (done in O(1) time). However, accessing elements for inserting and deleting in a linked list is not efficient (O(n) time). Imagine having to move through the whole list to get to the last element. Building the dynamic array is less efficient, because of the need to re-size the array as it grows. Inserting and deleting elements is less efficient because of need to move all the elements after to make room or fill the gap. However accessing an element in an array is efficient (O(1) time) and there are big advantages when it comes to sorting.
The Java ArrayList is an implementation of a dynamic array. You could also implement your own.
If you can't use an ArrayList, or any kind of dynamic list at all, then one solution would be this:
StringBuilder sb = new StringBuilder();
Scanner scanner = new Scanner(System.in);
int j;
while((j=scanner.nextInt()) !=-1){
sb.append(j + " ");
}
String []numbers = sb.toString().split(" ");
int[] grades = new int[numbers.length];
for(int i=0;i<numbers.length;i++){
grades[i] = Integer.parseInt(numbers[i]);
}
As you can see, I'm putting the input in a stringbuilder object, then I parse it in an array of strings, and convert that array in an integer array.
I hope this helps.
I am looking to print out my original unsorted array, I have it printing in order and sorted but I can't seem to get the original one to print out unsorted. I have used printRuleAndArray(String rule) and I have also used LengthCompare for the new sorted array, my problem is the original!!!
import java.util.*;
import java.util.Arrays;
// Example of how to sort an array
public class Sorting2
{
//declare an array of strings
static String[] nameArray = {"Alan", "Peter", "Ed", "Stephen", "Pheadraa"};
public static void main(String[] args)
{
// sorting by length
Arrays.sort(nameArray, new LengthCompare());
//print out elements of array
System.out.println(Arrays.toString(nameArray));
//count the number of elements in the array
int counter=nameArray.length;
//print out numeric number of elements in array
System.out.println("Number of elements in array: " + counter);
//print out sorted array with shortest first and longest last
printRuleAndArray("Sorted list by name length:");
}
Arrays.sort() will always sort the array you pass into it, it doesn't produce a fresh copy - so if you really need the unsorted array to hang around as well as the sorted array, then you'll have to make a copy of it:
String copyArr[] = new String[nameArray.length];
System.arraycopy( nameArray, 0, copyArr, 0, nameArray.length );
However, preferable to this approach (if feasible) would just be to do all the operations you need on the unsorted array (such as printing it or converting it to a string), then sort it afterwards.
As pointed out in the comment, Arrays.copyOf() could also be used to accomplish the same thing.
Arrays.sort will have altered your original array. Your choices are to either print your original array before sorting it, or to copy your original array and sort the copy.
Call String unsortedArr = Arrays.toString(nameArray); before array sorting, and when you need to print unsorted array just call System.out.println(unsortedArr);
Arrays.sort() sorts the array you pass into it. If you would like the original array later, copy the array first and then sort that array.
for(String arr : nameArray ) { //arr gets successively each value in nameArray.
System.out.println(arr);
}
this example is using foreach loop
Do something like this
String orig = Arrays.toString(nameArray);
Arrays.sort(nameArray, new LengthCompare());
String sorted = Arrays.toString(nameArray);
System.out.println(orig);
System.out.println(sorted);
What is the difference between
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); // Copy
List<Integer> list2 = Arrays.asList(ia);
, where ia is an array of integers?
I came to know that some operations are not allowed in list2. Why is it so?
How is it stored in memory (references / copy)?
When I shuffle the lists, list1 doesn't affect the original array, but list2 does. But still list2 is somewhat confusing.
How does ArrayList being upcasted to list differ from creating a new ArrayList?
list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
First, let's see what this does:
Arrays.asList(ia)
It takes an array ia and creates a wrapper that implements List<Integer>, which makes the original array available as a list. Nothing is copied and all, only a single wrapper object is created. Operations on the list wrapper are propagated to the original array. This means that if you shuffle the list wrapper, the original array is shuffled as well, if you overwrite an element, it gets overwritten in the original array, etc. Of course, some List operations aren't allowed on the wrapper, like adding or removing elements from the list, you can only read or overwrite the elements.
Note that the list wrapper doesn't extend ArrayList - it's a different kind of object. ArrayLists have their own, internal array, in which they store their elements, and are able to resize the internal arrays etc. The wrapper doesn't have its own internal array, it only propagates operations to the array given to it.
On the other hand, if you subsequently create a new array as
new ArrayList<Integer>(Arrays.asList(ia))
then you create new ArrayList, which is a full, independent copy of the original one. Although here you create the wrapper using Arrays.asList as well, it is used only during the construction of the new ArrayList and is garbage-collected afterwards. The structure of this new ArrayList is completely independent of the original array. It contains the same elements (both the original array and this new ArrayList reference the same integers in memory), but it creates a new, internal array, that holds the references. So when you shuffle it, add, remove elements etc., the original array is unchanged.
Well, this is because ArrayList resulting from Arrays.asList() is not of the type java.util.ArrayList.
Arrays.asList() creates an ArrayList of type java.util.Arrays$ArrayList which does not extend java.util.ArrayList, but only extends java.util.AbstractList.
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
In this case, list1 is of type ArrayList.
List<Integer> list2 = Arrays.asList(ia);
Here, the list is returned as a List view, meaning it has only the methods attached to that interface. Hence why some methods are not allowed on list2.
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
Here, you are creating a new ArrayList. You're simply passing it a value in the constructor. This is not an example of casting. In casting, it might look more like this:
ArrayList list1 = (ArrayList)Arrays.asList(ia);
First of all, the Arrays class is a utility class which contains a number of utility methods to operate on Arrays (thanks to the Arrays class. Otherwise, we would have needed to create our own methods to act on Array objects)
asList() method:
asList method is one of the utility methods of Array class, it is a static method that's why we can call this method by its class name (like Arrays.asList(T...a) )
Now here is the twist. Please note that this method doesn't create new ArrayList object. It just returns a List reference to an existing Array object (so now after using asList method, two references to existing Array object gets created)
and this is the reason. All methods that operate on List object, may not work on this Array object using the List reference. Like
for example, Arrays size is fixed in length, hence you obviously can not add or remove elements from Array object using this List reference (like list.add(10) or list.remove(10);. Else it will throw UnsupportedOperationException).
any change you are doing using a list reference will be reflected in the exiting Arrays object (as you are operating on an existing Array object by using a list reference)
In the first case, you are creating a new Arraylist object (in the second case, only a reference to existing Array object is created, but not a new ArrayList object), so now there are two different objects. One is the Array object and another is the ArrayList object and there isn't any connection between them (so changes in one object will not be reflected/affected in another object (that is, in case 2, Array and Arraylist are two different objects)
Case 1:
Integer [] ia = {1,2,3,4};
System.out.println("Array : "+Arrays.toString(ia));
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); // new ArrayList object is created , no connection between existing Array Object
list1.add(5);
list1.add(6);
list1.remove(0);
list1.remove(0);
System.out.println("list1: " + list1);
System.out.println("Array: " + Arrays.toString(ia));
Case 2:
Integer [] ia = {1,2,3,4};
System.out.println("Array: " + Arrays.toString(ia));
List<Integer> list2 = Arrays.asList(ia); // Creates only a (new) List reference to the existing Array object (and NOT a new ArrayList Object)
// list2.add(5); // It will throw java.lang.UnsupportedOperationException - invalid operation (as Array size is fixed)
list2.set(0,10); // Making changes in the existing Array object using the List reference - valid
list2.set(1,11);
ia[2]=12; // Making changes in the existing Array object using the Array reference - valid
System.out.println("list2: " + list2);
System.out.println("Array: " + Arrays.toString(ia));
An explanation with documentation references would be better for someone looking for answer.
1. java.util.Arrays
This is a utility class with bunch of static methods to operate on given array
asList is one such static method that takes input array and returns an object of java.util.Arrays.ArrayList which is a static nested class that extends AbstractList<E> which in turn implements List interface.
So Arrays.asList(inarray) returns a List wrapper around the input array, but this wrapper is java.util.Arrays.ArrayList and not java.util.ArrayList and it refers to the same array, so adding more elements to the List wrapped array would affect the original one too and also we cannot change the length.
2. java.util.ArrayList
ArrayList has a bunch of overloaded constructors
public ArrayList() - // Returns arraylist with default capacity 10
public ArrayList(Collection<? extends E> c)
public ArrayList(int initialCapacity)
So when we pass the Arrays.asList returned object, i.e., List(AbstractList) to the second constructor above, it will create a new dynamic array (this array size increases as we add more elements than its capacity and also the new elements will not affect the original array) shallow copying the original array (shallow copy means it copies over the references only and does not create a new set of same objects as in original array)
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> namesList = Arrays.asList(names);
or
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> temp = Arrays.asList(names);
The above statement adds the wrapper on the input array. So the methods like add and remove will not be applicable on the list reference object 'namesList'.
If you try to add an element in the existing array/list then you will get "Exception in thread "main" java.lang.UnsupportedOperationException".
The above operation is readonly or viewonly.
We can not perform add or remove operation in list object.
But
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names));
or
String names[] = new String[]{"Avinash","Amol","John","Peter"};
java.util.List<String> listObject = Arrays.asList(names);
java.util.ArrayList<String> list1 = new ArrayList<>(listObject);
In the above statement you have created a concrete instance of an ArrayList class and passed a list as a parameter.
In this case, methods add and remove will work properly as both methods are from ArrayList class, so here we won't get any UnSupportedOperationException.
Changes made in the Arraylist object (method add or remove an element in/from an arraylist) will get not reflect in to the original java.util.List object.
String names[] = new String[] {
"Avinash",
"Amol",
"John",
"Peter"
};
java.util.List < String > listObject = Arrays.asList(names);
java.util.ArrayList < String > list1 = new ArrayList < > (listObject);
for (String string: list1) {
System.out.print(" " + string);
}
list1.add("Alex"); // Added without any exception
list1.remove("Avinash"); // Added without any exception will not make any changes in original list in this case temp object.
for (String string: list1) {
System.out.print(" " + string);
}
String existingNames[] = new String[] {
"Avinash",
"Amol",
"John",
"Peter"
};
java.util.List < String > namesList = Arrays.asList(names);
namesList.add("Bob"); // UnsupportedOperationException occur
namesList.remove("Avinash"); // UnsupportedOperationException
Note that, in Java 8, 'ia' above must be Integer[] and not int[]. Arrays.asList() of an int array returns a list with a single element. When using the OP's code snippet, the compiler will catch the issue, but some methods (e.g., Collections.shuffle()) will silently fail to do what you expect.
Many people have answered the mechanical details already, but it's worth noting:
This is a poor design choice, by Java.
Java's asList method is documented as "Returns a fixed-size list...". If you take its result and call (say) the .add method, it throws an UnsupportedOperationException. This is unintuitive behavior! If a method says it returns a List, the standard expectation is that it returns an object which supports the methods of interface List. A developer shouldn't have to memorize which of the umpteen util.List methods create Lists that don't actually support all the List methods.
If they had named the method asImmutableList, it would make sense. Or if they just had the method return an actual List (and copy the backing array), it would make sense. They decided to favor both runtime-performance and short names, at the expense of violating both the principle of least astonishment and the good object-oriented practice of avoiding UnsupportedOperationExceptions.
(Also, the designers might have made a interface ImmutableList, to avoid a plethora of UnsupportedOperationExceptions.)
package com.copy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class CopyArray {
public static void main(String[] args) {
List<Integer> list1, list2 = null;
Integer[] intarr = { 3, 4, 2, 1 };
list1 = new ArrayList<Integer>(Arrays.asList(intarr));
list1.add(30);
list2 = Arrays.asList(intarr);
// list2.add(40); Here, we can't modify the existing list,because it's a wrapper
System.out.println("List1");
Iterator<Integer> itr1 = list1.iterator();
while (itr1.hasNext()) {
System.out.println(itr1.next());
}
System.out.println("List2");
Iterator<Integer> itr2 = list2.iterator();
while (itr2.hasNext()) {
System.out.println(itr2.next());
}
}
}
Arrays.asList()
This method returns its own implementation of List. It takes an array as an argument and builds methods and attributes on top of it, since it is not copying any data from an array but using the original array this causes alteration in original array when you modify list returned by the Arrays.asList() method.
On the other hand, ArrayList(Arrays.asList());
is a constructor of ArrayList class which takes a list as argument and returns an ArrayList that is independent of list, i.e., Arrays.asList() in this case passed as an argument.
That is why you see these results.
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia)); //copy
2.List<Integer> list2 = Arrays.asList(ia);
In line 2, Arrays.asList(ia) returns a List reference of inner class object defined within Arrays, which is also called ArrayList but is private and only extends AbstractList. This means what returned from Arrays.asList(ia) is a class object different from what you get from new ArrayList<Integer>.
You cannot use some operations to line 2 because the inner private class within Arrays does not provide those methods.
Take a look at this link and see what you can do with the private inner class:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Arrays.java#Arrays.ArrayList
Line 1 creates a new ArrayList object copying elements from what you get from line 2. So you can do whatever you want since java.util.ArrayList provides all those methods.
In response to some comments asking questions about the behaviour of Arrays.asList() since Java 8:
int[] arr1 = {1,2,3};
/*
Arrays are objects in Java, internally int[] will be represented by
an Integer Array object which when printed on console shall output
a pattern such as
[I#address for 1-dim int array,
[[I#address for 2-dim int array,
[[F#address for 2-dim float array etc.
*/
System.out.println(Arrays.asList(arr1));
/*
The line below results in Compile time error as Arrays.asList(int[] array)
returns List<int[]>. The returned list contains only one element
and that is the int[] {1,2,3}
*/
// List<Integer> list1 = Arrays.asList(arr1);
/*
Arrays.asList(arr1) is Arrays$ArrayList object whose only element is int[] array
so the line below prints [[I#...], where [I#... is the array object.
*/
System.out.println(Arrays.asList(arr1));
/*
This prints [I#..., the actual array object stored as single element
in the Arrays$ArrayList object.
*/
System.out.println(Arrays.asList(arr1).get(0));
// prints the contents of array [1,2,3]
System.out.println(Arrays.toString(Arrays.asList(arr1).get(0)));
Integer[] arr2 = {1,2,3};
/*
Arrays.asList(arr) is Arrays$ArrayList object which is
a wrapper list object containing three elements 1,2,3.
Technically, it is pointing to the original Integer[] array
*/
List<Integer> list2 = Arrays.asList(arr2);
// prints the contents of list [1,2,3]
System.out.println(list2);
Summary of the difference -
When a list is created without using the new, the operator Arrays.asList() method returns a wrapper which means:
you can perform an add/update operation.
the changes done in the original array will be reflected to List as well and vice versa.