I am facing a very simple issue :
List<String> myList = new Vector<String>(10);
myList.add(5,"HELLO");
gives me ArrayOutOfBoundException : 5>0
Is there a way to specify the size of a Vector and fill the list in random order?
You're not specifying the size, you're specifying the capacity of Vector.
You could do:
List<String> myList = new Vector<String>();
for(int i = 0;i < 10; i++)
myList.add(null);
myList.set(5, "HELLO");
What you should do is forget the Vector class, since it's been outdated for over 10 years already.
If you just need fixed size and random access, you can use an array
String[] myArr = new String[10];
If you need it to be a Collection, you can use
List<String> myList = Arrays.asList(myArr);
Finally if you want to add more elements in it (Arrays.asList() returns a fixed size list) you can use
List<String> myList = new ArrayList<>(Arrays.asList(myArr));
The documentation of the add() method explicitly states:
ArrayIndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())
Since your size at the moment is 0, the behaviour is as expected.
The constructor of the Vector class specifies the initial capacity, not the size of the collection.
After checking out what was said in the comments, I am removing my suggestion. It's better to stick to arrays in that case.
Related
The problem
I have an ArrayList of ArrayLists. I am copying one over to the other, except in a different order (a rotation of the elements by 180°, but that's not important).
I have this generic code:
ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>>();
for (int r = 0; r < 4; r++) {
for (int c = 0; c < 5; c++) {
list.get(r).set(c, "an element from the other list");
}
}
I'm arbitrarily using sizes 4 for the number of rows and 5 for the number of columns.
However, this throws an index out of bounds error, obviously because I have no dimensions for the ArrayList<ArrayList<String>>.
I know that when creating an ArrayList, you can give it an initial capacity for a constructor parameter. However, I don't know how to apply that to this:
ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>>();
This won't compile, but this is essentially what I want:
ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>(5)>(4);
My mediocre solution
To give the matrix some dimensions before I attempted to copy the list over, I just iterated for the number of rows I wanted and added a list of size of the number of columns I wanted to each row.
I used a regular array and converted it to an ArrayList just so that the elements would have a default value of null, and so would contribute to the size.
for (int r = 0; r < 4; r++) {
// list.add( new ArrayList<String>(5) ); // doesn't work
list.add( new ArrayList<String>( Arrays.asList(new String[5]) ) );
}
So that works for setting the size, because enough elements will be added to the matrix, but it's not the preferred solution.
The question
Is there any way to set the initial dimensions of an ArrayList of ArrayLists during the initialization? Or just something different that iterating and adding null values?
This works for me:
ArrayList<ArrayList<String>> list = new ArrayList<ArrayList<String>>(4);
for (int r = 0; r < 4; r++) {
ArrayList<String> ls = new ArrayList<String>(5);
ls.add("" + (r + 1));
list.add(ls);
}
for (ArrayList<String> ls : list) {
System.out.println(ls);
}
Note: do not confuse ArrayList#size(), current number of elements in the collection, with ArrayList#capacity, current maximum size of the collection (which cannot be accessed).
For more info, refer to: ArrayList(int):
Constructs an empty list with the specified initial capacity.
Note that using List<List<Whatever>> you're not creating a 2D dynamic array, you're creating a dynamic list which will contains dynamic lists, thus you must initialize every list by separate and add lists (from any size) into another list, and every list would have a dynamic size (despite the values they have). There's no 2d dynamic array nor dynamic array of arrays in plain Java, unless you create such class or import it from a third party library.
Looks like this structure would suit better for your case:
String[][] stringArrayOfArray = new String[4][5];
Another very odd way (not recommended) to accomplish what you want/need would be:
List<String>[] arrayOfList = new List[4];
for (int i = 0; i < arrayOfList.length; i++) {
arrayOfList[i] = new ArrayList<String>();
}
I am getting some weird running times for my mergesort algorithm...I want to run the algorithm (say 1000 times) on the same permuted ArrayList. Right now, I just create an array of ArrayList of size 1000, then time how long it takes to sort each of these, then take the average of the times.
So my question is: am I sorting the same list over and over? If I change one instance of the ArrayList in the array say at index 0, will the other ArrayLists in the array stay the same? I would assume so, but I want to be certain that's not happening? Thanks.
for (int N = 1000; N <= 10000; N += 1000) {
//copy the array
#SuppressWarnings("unchecked")
ArrayList<Integer>[] container = (ArrayList<Integer>[])new ArrayList[N];
ArrayList<Integer> testArray1 = generatePermutedOrder(N);
for(int j=0; j<timesToLoop; j++){
container[j] = testArray1;
}
System.out.print(N + "\t");
// let things stabilize
startTime = System.nanoTime();
while (System.nanoTime() - startTime < 1000000000)
;
// time the routine
startTime = System.nanoTime();
for (int i = 0; i < timesToLoop; i++) {
mergesort(container[i]);
}
If I change one instance of the ArrayList in the array say at index 0, will the other ArrayLists in the array stay the same?
Yes, modifying ArrayList at index 0 won't effect the other indexes. (but make sure that other indexes don't have reference to same ArrayList)
Scenerio 1: (Modifying index 0 will effect index 1)
ArrayList[] arr = new ArrayList[2];
ArrayList aList = new ArrayList();
arr[0] = aList;
arr[1] = aList;
Scenerio 2: (Modifying index 0 will NOT effect index 1)
ArrayList[] arr = new ArrayList[2];
ArrayList aList1 = new ArrayList();
ArrayList aList2 = new ArrayList();
arr[0] = aList1;
arr[1] = aList2;
So, make sure it's Scenerio 2 in your code.
EDIT:
ArrayList<Integer> testArray1 = generatePermutedOrder(N);
for(int j=0; j<timesToLoop; j++)
{
container[j] = testArray1; // same reference pointing to same ArrayList is added in each interation
}
You are adding same reference to each index. So, modifying at any index will effect remaining indexes.
Yes the other ArrayList will stay the same.
For example.
array[0].set(0,object)
Will not affect the ArrayList at array[1]
You said you created an array of ArrayLists, but what did you assign into each slot in that array? Did you create one ArrayList instance and assign it to all 1000 slots in the array, or did you create 1000 different ArrayLists (e.g. using new in a loop) and assign a different one to each array slot?
If you store multiple references to the same object in multiple places, changes to that object will be visible through all the references.
If you just create an array of ArrayList objects they're all null. If you then iterate through the array and instantiate each ArrayList with new, then they're all different (each call to new ArrayList() will create a new one).
It's possible to put the same ArrayList reference in every element of the array by creating an ArrayList and then iterating through the array and assigning every element of the array the value of the (already created) ArrayList. This is probably not what you want to do.
I have an array like this:
String n[] = {"google","microsoft","apple"};
What I want to do is to remove "apple".
My problem is very basic,however,I searched the website and I found out that java doesn't really support the deleting feature from an array.I also heard to use Java Utils, because it's so simple to remove an item....I tried to find Java Utils on google, but almost all links are dead.
So finally...is there any way to remove a string from an array of string?
Even if I use an ArrayList I can't find a method to generate a random item in it! For ex: in a normal array I generate a string like this:
String r = myAL[rgenerator.nextInt(myAL.length)];
In an arraylist it doesn't work....maybe you know a solution...
Define "remove".
Arrays are fixed length and can not be resized once created. You can set an element to null to remove an object reference;
for (int i = 0; i < myStringArray.length(); i++)
{
if (myStringArray[i].equals(stringToRemove))
{
myStringArray[i] = null;
break;
}
}
or
myStringArray[indexOfStringToRemove] = null;
If you want a dynamically sized array where the object is actually removed and the list (array) size is adjusted accordingly, use an ArrayList<String>
myArrayList.remove(stringToRemove);
or
myArrayList.remove(indexOfStringToRemove);
Edit in response to OP's edit to his question and comment below
String r = myArrayList.get(rgenerator.nextInt(myArrayList.size()));
It is not possible in on step or you need to keep the reference to the array.
If you can change the reference this can help:
String[] n = new String[]{"google","microsoft","apple"};
final List<String> list = new ArrayList<String>();
Collections.addAll(list, n);
list.remove("apple");
n = list.toArray(new String[list.size()]);
I not recommend the following but if you worry about performance:
String[] n = new String[]{"google","microsoft","apple"};
final String[] n2 = new String[2];
System.arraycopy(n, 0, n2, 0, n2.length);
for (int i = 0, j = 0; i < n.length; i++)
{
if (!n[i].equals("apple"))
{
n2[j] = n[i];
j++;
}
}
I not recommend it because the code is a lot more difficult to read and maintain.
Arrays in Java aren't dynamic, like collection classes. If you want a true collection that supports dynamic addition and deletion, use ArrayList<>. If you still want to live with vanilla arrays, find the index of string, construct a new array with size one less than the original, and use System.arraycopy() to copy the elements before and after. Or write a copy loop with skip by hand, on small arrays the difference will be negligible.
You can't remove anything from an array - they're always fixed length. Once you've created an array of length 3, that array will always have length 3.
You'd be better off with a List<String>, e.g. an ArrayList<String>:
List<String> list = new ArrayList<String>();
list.add("google");
list.add("microsoft");
list.add("apple");
System.out.println(list.size()); // 3
list.remove("apple");
System.out.println(list.size()); // 2
Collections like this are generally much more flexible than working with arrays directly.
EDIT: For removal:
void removeRandomElement(List<?> list, Random random)
{
int index = random.nextInt(list.size());
list.remove(index);
}
import java.util.*;
class Array {
public static void main(String args[]) {
ArrayList al = new ArrayList();
al.add("google");
al.add("microsoft");
al.add("apple");
System.out.println(al);
//i only remove the apple//
al.remove(2);
System.out.println(al);
}
}
I set an array of integer like below
int[] a = new int[11111];
//if I set
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
I want a method such that it gives me
4 but 11111.
Is there any method which I can use?
You should look into using an ArrayList
ArrayList<Integer> myList=new ArrayList<Integer>();
myList.add(1);
myList.add(2);
myList.add(3);
System.out.println("Size:"+myList.size());
Well, the following method will do what you asked for:
public int m() {
return 4;
}
On the assumption that you want a method that takes an array, and returns the greatest index that has been populated - you're right that the a.length only tells you the size of the array, i.e. the number of cells allocated.
This is going to be harder than you might expect, especially with an int array. Those unassigned cells are initialised to a value of 0. If you might actually use zero values in your array, then there is absolutely no way to tell whether the value in a cell is the "default" zero or one that you've set yourself.
If the array can't have zero values in it, then you'd need to loop over its entire length, checking for the highest index with a corresponding non-zero value; something like this:
public int dynamicLength(int[] a) {
int max = -1;
for (i = 0; i < a.length; i++) {
if (a[i] != 0) max = i;
}
return max;
}
Even then this might not be ideal, since arrays can be sparsely populated. Do you want the count of assigned indices, or the index of the highest assigned index?
The short answer is almost certainly "use an ArrayList".
When you do
int[] a = new int[11111]
It creates an array with 11111 elements and as it is int it will assign it to default value that is 0 so you have array with all values set.
You should move to List
You should use an ArrayList if the size of the array is changing. There is little performance difference.
See here for how to use one. See here for the API also.
I understand that you only want the assigned elements to be counted but it would be safer at runtime and simpler to use an ArrayList. The ArrayList class just wraps a Java array and handles the changing size for you. You can get the size by calling the size() method on the ArrayList.
See this example using a for-each loop if you want to iterate over the elements:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1); //size is 1
list.add(2); //size is 2
list.add(3); //size is 3
list.add(4); //size is 4
for(Integer n : list)
System.out.println(n);
An ArrayList uses an iterator and the for-each loop uses it to iterate over the ArrayList. Makes life much simpler.
As suggested above, using a List is probably the right answer. However, in the interest of solving the original problem, you could try this instead:
Integer[] foo = new Integer[11111];
foo[0] = new Integer(1);
foo[1] = new Integer(2);
foo[2] = new Integer(3);
foo[3] = new Integer(4);
and create a method that counts non-null values:
public static int countItems(Integer[] array) {
int count = 0;
for (Integer i : array) {
if (i != null) {
count++;
}
}
return count;
}
Of course, this will be a pain to manage as you would need to nullify any items no longer needed. It also raises the question of whether you would accept "holes" in your array, e.g. null values amongst non-null values. My example counting function above would accept such holes.
So, yes. Use a List.
You can create a method which calculates the non-0 elements of the array using a for/while loop.
How can I filter an array in Java?
I have an array of objects, for example cars:
Class:
public class Car{
public int doors;
public Car(int d){
this.doors = d;
}
}
Use:
Car [] cars = new Cars[4];
cars[0] = new Car(3);
cars[1] = new Car(2);
cars[2] = new Car(4);
cars[3] = new Car(6);
Now I want to filter the array of cars, keeping only 4 doors and more:
for(int i = 0; i<cars.length; i++){
if(cars[i].doors > 4)
//add cars[i] to a new array
}
}
How should I do this?
Before I did it with a Vector:
Vector subset = new Vector();
for(int i = 0; i<cars.length; i++){
if(cars[i].doors > 4)
//add cars[i] to a new array
subset.addElement(cars[i]);
}
}
And then I would make a new array with the size of the Vector. Then I would loop over the vector again and fill the new array. I know this is a very large procedure for something simple.
I'm using J2ME.
EDIT: saw that ArrayList is not in J2ME, but based on documentation, it does have a Vector. If that Vector class is different than J2SE Vector (as this documentation indicates), then perhaps the following code would work:
Vector carList = new Vector();
for(int i = 0; i<cars.length; i++){
if(cars[i].doors > 4)
carList.addElement(cars[i]);
}
}
Car[] carArray = new Car[carList.size()];
carList.copyInto(carArray);
The most efficient way to do this--if the predicate you're filtering on is inexpensive and you're accessing it with a single thread--is usually to traverse the list twice:
public Car[] getFourDoors(Car[] all_cars) {
int n = 0;
for (Car c : all_cars) if (c.doorCount()==4) n++;
Car[] cars_4d = new Car[n];
n = 0;
for (Car c : all_cars) if (c.doorCount()==4) cars_4d[n++] = c;
return cars_4d;
}
This traverses the list twice and calls the test twice, but has no extra allocations or copying. The Vector-style methods traverse the list once, but allocates about twice the memory it needs (transiently) and copies every good element about twice. So if you are filtering a tiny fraction of the list (or performance isn't an issue, which very often it isn't), then the Vector method is good. Otherwise, the version above performs better.
If you really need a plain array as the result, I think your way is the way to go: you don't know the number of resulting elements before you filter, and you can't construct a new array without knowing the number of elements.
However, if you don't need thread-safety, consider using ArrayList instead of a Vector. It ought to be somewhat faster. Then use ArrayList's toArray method to get the array.
I can't see much wrong with your code. You could just stick with Vectors throughout though.
You could simplify the second part (where you copy the matching items into the new array) using Vector.copyInto(Object[]).
There's no direct way to remove elements from an array; its size is fixed. Whatever you do, you need to allocate a new array somehow.
If you want to avoid the minor memory overhead of allocating a Vector, another option would be to make two passes over your array. The first time, simply count the number of elements that you want to keep. Then allocate an array that size, and loop over your old array again, copying matching elements into the new array.
You can use System.arrayCopy():
Car[] cars = ...
int length = cars.length < 4 ? cars.length() : 4;
Car filter = new Car[4];
System.arrayCopy(cars, 0, filter, 0, length);
UPDATE: System.arrayCopy is available in Java ME API, unlike Vector.subList(). Thanks for the correction.
You will need to create a new array anyway.
Vector vector = new Vector(array.length);
for (int i = 0; i < array.length; i++) {
if (array[i].doors > 4) {
vector.add(array[i]);
}
}
Car[] result = new Car[vector.size()];
vector.copyInto(result);
This isn't quite efficient, though.