I am new to Java. I apologize if I ask a simple thing.
I wrote the below code but it seems that it doesn't initialize properly. because when I print the size of list1 it show the size = 0!! However, it should be 4!
public static class MyClass{
public List <Integer> list1
// Class Constructor
public MyClass(int n){
list1 = new ArrayList <Integer> (n);
System.out.println("Size = " + list1.size() );
// prints Size = 0 !!!why???
}
public void init(int n){
for(int cnt1 = 0; cnt1 < list1.size(); cnt1++){
list1.set(cnt1 , cnt1);
}
}
...}
public static List<Integer> Func1(int n){
MyClass = new myclass (n);
myclass.init(n);
... }
public static void main(String args[]){
int n = 4;
result = Func1 (n);
...}
Why the size of the list1 is 0? It should be 4, because I pass 4 to Func1, and then it creates MyClass object with size n.
I would be thankful if someone can help me about this problem.
Array lists in Java have both a size and a capacity.
Size tells you how many items are there in the list, while
Capacity tells you how many items the list can hold before it needs to resize.
When you call ArrayList(int) constructor, you set the capacity, not the size, of the newly created array list. That is why you see zero printed out when you get the size.
Having a capacity of 4 means that you can add four integers to the list without triggering a resize, yet the list has zero elements until you start adding some data to it.
You have used the ArrayList constructor that determines its initial capacity, not its initial size. The list has a capacity of 4, but nothing has been added yet, so its size is still 0.
Quoting from the linked Javadocs:
Constructs an empty list with the specified initial capacity.
Also, don't use set to add to the list. That method replaces an element that is already there. You must add to the list first (or use the other overloaded add method).
Related
I am trying to increase the size of an ArrayList inside an ArrayList whenever a new value is added but I'm not sure on the correct way to do so. This is what I have right now:
public ArrayList<ArrayList<Integer>> outerList;
public int addValue(int value) {
int a = 0;
ArrayList<Integer> innerList = new ArrayList<Integer>();
if (noValue(value) == true) { // noValue checks if the value exists at a position in outerList and returns true if it's empty
innerList.add(value); // innerList has now size 1
outerList.add(innerList);
}
else {
a += 1;
innerList.add(value);
outerList.add(innerList);
}
return a;
}
But based on my tests, the size of innerList remains 1.
But based on my tests, the size of innerList remains 1.
This is because in your addValue() method you create a new innerList and add it to the list. Thus your outer ArrayList will consist of a lot of ArrayList's with only one object in them.
To change this you should use the get() method to get the inner ArrayList and then add the item to it. Something like:
outerList.get(index).add(value);
Where index is the index of the inner list you want to add the value to
You never get anything from outerList, all instances of innerList will always be newly created and then get one new entry added. Then that innerList is added to outerList and never touched again.
Is it possible in initiate the ArrayList with fixed size so it may not increase more than that and initiate all the initial occupancy to 0? in actual forcing it to behave like an ordinary Array so we can use the add() upto to the array size.
Why not use normal array rather than ArrayList
ArrayList are basically simply an array with support for the situation where we may have to add more items. If we're not changing the size of that ArrayList than it's just like the conventional array
You can use
List<Integer> list = Arrays.asList(new Integer[desiredLength]);
to produce a fixed size List<Integer> in which all the elements are initialized to null. Then you can use list.set(index,value) to modify elements of that List. You can't use add though, since add changes the size of the List, which is not allowed in fixed sized lists.
If you want to initialize the List to non-null values, you can do something like this :
Integer[] arr = new Integer[desiredLength];
Arrays.fill(arr,0);
List<Integer> list = Arrays.asList(arr);
You can, by using only arraylist, ensure a minimum size of the arraylist:
ArrayList<T> myArrayList = new ArrayList();
myArrayList.ensureCapacity(n);
But that doesn't set a fixed size, just something bigger than n, and it doesn't prevent you to add more than n.
As mentioned by other, you are probably better off doing something else. If you really want to achieve that, you can write your own collection:
public class MyArrayList<T> {
ArrayList<T> arrayList;
int size;
public MyArrayList(int size) {
this.size = size;
arrayList = new ArrayList<>();
arrayList.ensureCapacity(size);
}
public void add(T x) {
if (arrayList.size() >= size) {
throw new IllegalStateException();
}
arrayList.add(x);
}
//remove, etc.. . You can even extend/implement arrayList/list if you want to do polymorphism.
}
How do I find the size of an ArrayList in Java? I do not mean the number of elements, but the number of indexes.
public static void main(String[] args) {
ArrayList hash = new ArrayList(5);
System.out.println(hash.size());
}
Prints out "0." Using:
System.out.println(hash.toArray().length);
Also prints out a "0."
I have looked in http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html but I do not see a method that will help me. Is my ArrayList reverting to a size of 0 if I do not add anything to it?
EDIT The assignment is to create a hash table using ArrayList. I am supposed to create a hash function using the formula
double hashkey = Math.floor(hash.size()*(Math.E*key-Math.floor(Math.E*key)));
Where key is an integer. hashkey then becomes the index where the value will be stored. I am using hash.size() as a placeholder at the moment, but that value should be the capacity of my ArrayList.
ArrayList.size() will give the current size.That's why hash.size() giving you the current size of your ArrayList hash. It will not give you the capacity.
You just initialized the list. Have not add any elements to your arraylist, that's why its giving 0.
There is no such method in the ArrayList API. The capacity of an ArrayList is hidden by design.
However, I think that your question is based on a misunderstanding.
How do I find the size of an ArrayList in Java? I do not mean the number of elements, but the number of indexes.
In fact, the size of a List, the number of elements in a List, and the number of indexes (i.e. indexable positions) for a List ... are all the same thing.
The capacity of an ArrayList is something different. It is the number of elements that the object could contain, without reallocating the list's backing array. However, the fact that the list has a capacity N does NOT mean that you can index up to N - 1. In fact, you can only index up to size() - 1, irrespective of the capacity.
Now to deal with your examples:
ArrayList list = new ArrayList(5);
System.out.println(list.size());
This prints out zero because the list has zero elements. The ArrayList() and ArrayList(int) constructors both create and return lists that are empty. The list currently has space for 5 elements (because you gave it an initial capacity of 5) but you can't index those slots.
System.out.println(list.toArray().length);
This prints zero because when you copy the list's contents to an array (using toArray()), the array is the same size as the list. By definition.
This does not mean that the list's backing array has changed. On the contrary, it is still big enough to hold 5 elements without reallocation ... just like before.
But ... I hear you say ... the array's length is zero!
Yes, but that is not the backing array! The toArray() method allocates a new array and copies the List contents into that array. It does NOT return the actual backing array.
Maybe you should encapsulate your ArrayList in a class and add another attribute private int capacity in that class as well.
public class AdvancedArrayList<T>
{
private int capacity;
private ArrayList<T> list;
public AdvancedArrayList<T>(int capacity)
{
this.capacity = capacity;
list = new ArrayList<>();
}
public ArrayList<T> getList()
{
return list;
}
public int getCapacity()
{
return capacity;
}
public void addElement(T element)
{
if(list.size() < capacity)
list.add(element);
else
System.out.println("Capacity is full");
}
}
Notice that size is different than capacity.
When I do
ArrayList<Integer> arr = new ArrayList<Integer>(10);
arr.set(0, 1);
Java gives me
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.set(Unknown Source)
at HelloWorld.main(HelloWorld.java:13)
Is there an easy way I can pre-reserve the size of ArrayList and then use the indices immediately, just like arrays?
How about this:
ArrayList<Integer> arr = new ArrayList<Integer>(Collections.nCopies(10, 0));
This will initialize arr with 10 zero's. Then you can feel free to use the indexes immediately.
Here's the source from ArrayList:
The constructor:
public ArrayList(int initialCapacity)
{
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
You called set(int, E):
public E set(int index, E element)
{
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
Set calls rangeCheck(int):
private void rangeCheck(int index)
{
if (index >= size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
It may be subtle, but when you called the constructor, despite initializing an Object[], you did not initialize size. Hence, from rangeCheck, you get the IndexOutOfBoundsException, since size is 0. Instead of using set(int, E), you can use add(E e) (adds e of type E to the end of the list, in your case: add(1)) and this won't occur. Or, if it suits you, you could initialize all elements to 0 as suggested in another answer.
I believe the issue here is that although you have suggested the allocated space of entries in the Array, you have not actually created entries.
What does arr.size() return?
I think you need to use the add(T) method instead.
Programming aside, what you are trying to do here is illogical.
Imagine an empty egg carton with space for ten eggs. That is more or less what you have created. Then you tell a super-precise-and-annoying-which-does-exactly-what-you-tell-him robot to replace the 0th egg with another egg. The robot reports an error. Why? He can't replace the 0th egg, because there is no egg there! There is a space reserved for 10 eggs, but there are really no eggs inside!
You could use arr.add(1), which will add 1 in the first empty cell, i.e. the 0-indexed one.
Or you could create your own list:
public static class PresetArrayList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
public PresetArrayList(int initialCapacity) {
super(initialCapacity);
addAll(Collections.nCopies(initialCapacity, (E) null));
}
}
Then:
List<Integer> list = new PresetArrayList<Integer>(5);
list.set(3, 1);
System.out.println(list);
Prints:
[null, null, null, 1, null]
This is not an Java-specific answer but an data structure answer.
You are confusing the Capacity concept with the Count (or Size) one.
Capacity is when you tell the list to reserve/preallocate a number of slots in advance (in this ArrayList case, you are saying to it create an array of 10 positions) in its' internal storage. When this happens, the list still does not have any items.
Size (or Count) is the quantity of items the list really have. In your code, you really doesn't added any item - so the IndexOutOfBoundException is deserved.
While you can't do what you want with arraylist, there is another option: Arrays.asList()
Capacity is used to prepare ArrayLists for expansion. Take the loop
List<Integer> list = new ArrayList<>();
for(final int i = 0; i < 1024; ++i) {
list.add(i);
}
list starts off with a capacity of 10. Therefore it holds a new Integer[10] inside. As the loop adds to the list, the integers are added to that array. When the array is filled and another number is added, a new array is allocated twice the size of the old one, and the old values are copied to the new ones. Adding an item is O(1) at best, and O(N) at worst. But adding N items will take about 2*1024 individual assignments: amortized linear time.
Capacity isn't size. If you haven't added to the array list yet, the size will be zero, and attempting to write into the 3rd element will fail.
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.