How to reduce array size without creating new? - java

I am using array for storing a kind of object. I created an array of some fixed size
int arr[]=new int[n];
Now after processing this array i want to free upto 75% of the memory from this array(now only n/4 elements are useful). So what my question is, since n is very large and i wish not to hold larger memory than useful, How can i reduce size of array at runtime without copying to new array of size n/4(Is it even possible or not?).

It's not possible. You cannot change the length of an array after you initialise it.
What you can do is create another array with suitable size and make this large array eligible for Garbage Collector.
Best is to use ArrayList if you are allowed to do that.

It's not possible at all. Eventhough you are using collections for creating they are copying the array elements to newer size array if the array size exceeds!

No, Once you created an array then its size is fixed. You cant change it at run time. For your current scenario you can copy your useful elements to new array. Or just keep the array don't care about the memory.

Related

How can I resize array in java? [duplicate]

This question already has answers here:
Resize an Array while keeping current elements in Java?
(12 answers)
Closed 3 months ago.
As the title, how can I resize array in java, without importing any library, including ArrayList, Arrays.copyOf ...etc.
Also, I have to resize again and again in my program, with the unknown input data.( i.e. I have a small array, but when the data increasing, how can I resize it?)
Unfortunately, you cant resize an array in java.
Some things you could do are:
When new data is taken in, make a new array and copy the old array + the new data.
Use an ArrayList which makes the array bigger as you add data to it.
Use java.util.Arrays.copyOf(...). This returns a bigger array with the contents of the previous array.
Java does not have a "resize" option for allocated storage. You must allocate new storage of the required size and copy the data from the old storage to the new.
You can use System.arraycopy() to copy the data. The ArrayList and Vector classes automatically perform these reallocate and copy operations, so if you don't use them, you are reinventing the wheel.
java.lang.System is, of course, automatically imported into every java program, so, as required, you don't need import java.lang.System; to implement this.
a array is by definition fixed in size, I know many modern languages let you assign the length and change the length dynamically
but I think what you are looking for is a Vector
https://docs.oracle.com/javase/7/docs/api/java/util/Vector.html
it allows O(1) access (like the array) while beeing dynamic in length
You can not increase the size of an array once it is declared. So you have to use Collection framework in java, may be ArrayList or LinkedList.
That is what is the difference between Array and ArrayList. In ArrayList you can add element dynamically,no need to increase it's size.
you could use forEach to copy the values to the enlarged new array
IntStream.range( 0, oldArray.length ).forEach( i -> newArray[i] = oldArray[i] );

Techniques to redimension an array in Java : is "nullifying" the array bad?

I'm learning Java and surprisingly I found out that Java arrays are not dynamic - even though its cousing languages have dynamic arrays.
So I came out with ideas to kind of imitate a dynamic array in java on my own.
One thought I had was to copy the original array references to a temporary array, then turn the original array to null, re-set its index to a bigger value and then finally re-copy the values from the temporary array.
Example.:
if(numberOfEntries == array.length){
Type[] temp = new Type[numberOfEntries];
for(int x=0; x < numberOfEntries; x++){
temp[x] = array[x];
}
array = null;
array = new Type[numberOfEntries+1];
for(int x=0; x < numberOfEntries; x++){
array[x] = temp[x];
}
I know that this can result in data loss if the process is interrupted, but aside from that, is this a bad idea? What are my options?
Thanks!
Your idea is in the right ballpark. But for a task that you propose you should never implement your own version, unless it is for academic purposes and fun.
What you propose is roughly implemented by the ArrayList class.
This has an internal array and a size 'counter'. The internal array is filled when items are added. When the internal array is full all elements are copied to a bigger array. The internal array is never released to the user of the class (to make sure it's state is always valid).
In your example code, because an array is a pointer, you don't really need the temp array. Just create a new one, copy all elements and save the pointer to it as your array.
You might want to look into thrashing. Changing the size of the array by 1 is likely to be very inefficient. Depending on your use case, you might want to increase the array size by double, and similarly halve the array when it's only a quarter full.
ArrayList is convenient, but once it's full, it takes linear time to add an element. You can achieve something similar to resizing with the ensureCapacity() method. I'd recommend becoming more familiar with Java's Collections framework so you can make the best decisions in future by yourself.
Arrays are not dynamic their size can't change dynamically and right now you aren't changing the same object, you are replacing smaller size object with larger size object
int[5] Arr = new int[5] ; // Create an array of size 5
Arr = new int[10] ;// you assigned the different objects. It is not the same object.
So, we can't change the size of the array dynamically. You can use ArrayList for the same.
But keep try !!!
Please take a look at java.util.ArrayList which is dynamically, it is part of the Collections framework. Making the Array dynamically should be slower and error-prone.
Have you heard about time complexity , do you know how much time complexity you are increasing, Every time you are copying old array element to new array let you have 1 million element in array then think about copying time of element of one array to another array.
One more thing i want to tell you, ArrayList implementation used same logic except new length that you are using .

How to store sentences in a temporary array in Java?

Currently, I am scraping out a chunk of data (paragraphs/strings) from a text file and writing it out to a new file. However, I am planning on adding some conditionals later and thus want to be able to take out this chunk of data and only store it in a temporary array, then write out to a file if the conditionals are met. However, I am not sure how to write this out to an array without knowing the size of the array beforehand.
Does anyone have any ideas?
Don't use an array. Use a collection of type String that can grow dynamically such as an ArrayList for example. Here are some quick code samples: Sample 1, Sample 2
Some notes on an ArrayList's memory management from the Java docs:
The capacity is the size of the array
used to store the elements in the
list. It is always at least as large
as the list size. As elements are
added to an ArrayList, its capacity
grows automatically. The details of
the growth policy are not specified
beyond the fact that adding an element
has constant amortized time cost.
An application can increase the
capacity of an ArrayList instance
before adding a large number of
elements using the ensureCapacity
operation. This may reduce the amount
of incremental reallocation.
Notice that even the docs do not specify exactly how things are managed internally.
In Java, an ArrayList (or any other type of Java collection) can take care of all the memory management for you:
ArrayList<String> strings = new ArrayList<String>();
If you want to add a string:
strings.add("New String");
If you want to get a String at a certain index (in this example, index 1):
strings.get(1);
There are a lot more methods in the ArrayList class as well.
You do need a collection that grows dynamically. ArrayList is the first that comes to mind; internally it is very similar to a regular array, so it offers fast random access, if you need it. LinkedList may be better suited if you don't have an estimate about the number of elements that you will eventually need, provided that you will only need sequential access to its elements (random access is available, but it will not be fast).

How to define the concept of capacity in ArrayLists?

I understand that capacity is the number of elements or available spaces in an ArrayList that may or may not hold a value referencing an object. I am trying to understand more about the concept of capacity.
So I have three questions:
1) What are some good ways to define what capacity represents from a memory standpoint?
...the (contiguous?) memory allocated to the ArrayList?
...the ArrayLists’s memory footprint on the (heap?)?
2) Then if the above is true, changing capacity requires some manner of memory management overhead?
3) Anyone have an example where #2 was or could be a performance concern? Aside from maybe a large number of large ArrayLists having their capacities continually adjusted?
The class is called ArrayList because it's based on an array. The capacity is the size of the array, which requires a block of contiguous heap memory. However, note that the array itself contains only references to the elements, which are separate objects on the heap.
Increasing the capacity requires allocating a new, larger array and copying all the references from the old array to the new one, after which the old one becomes eligible for garbage collection.
You've cited the main case where performance could be a concern. In practice, I've never seen it actually become a problem, since the element objects usually take up much more memory (and possibly CPU time) than the list.
ArrayList is implemented like this:
class ArrayList {
private Object[] elements;
}
the capacity is the size of that array.
Now, if your capacity is 10, and you're adding 11-th element, ArrayList will do this:
Object[] newElements = new Object[capacity * 1.5];
System.arraycopy(this.elements, newElements);
this.elements = newElements;
So if you start off with a small capacity, ArrayList will end up creating a bunch of arrays and copying stuff around for you as you keep adding elements, which isn't good.
On the other hand, if you specify a capacity of 1,000,000 and add only 3 elements to ArrayList, that also is kinda bad.
Rule of thumb: if you know the capacity, specify it. If you aren't sure but know the upper bound, specify that. If you just aren't sure, use the defaults.
Capacity is as you described it -- the contiguous memory allocated to an ArrayList for storage of values. ArrayList stores all values in an array, and automatically resizes the array for you. This incurs memory management overhead when resizing.
If I remember correctly, Java increases the size of an ArrayList's backing array from size N to size 2N + 2 when you try to add one more element than the capacity can take. I do not know what size it increases to when you use the insert method (or similar) to insert at a specific position beyond the end of the capacity, or even whether it allows this.
Here is an example to help you think about how it works. Picture each space between the |s as a cell in the backing array:
| | |
size = 0 (contains no elements), capacity = 2 (can contain 2 elements).
|1| |
size = 1 (contains 1 element), capacity = 2 (can contain 2 elements).
|1|2|
size = 2, capacity = 2. Adding another element:
|1|2|3| | | |
size increased by 1, capacity increased to 6 (2 * 2 + 2). This can be expensive with large arrays, as allocating a large contiguous memory region can require a bit of work (as opposed to a LinkedList, which allocates many small pieces of memory) because the JVM needs to search for an appropriate location, and may need to ask the OS for more memory. It is also expensive to copy a large number of values from one place to another, which would be done once such a region was found.
My rule of thumb is this: If you know the capacity you will require, use an ArrayList because there will only be one allocation and access is very fast. If you do not know your required capacity, use a LinkedList because adding a new value always takes the same amount of work, and there is no copying involved.
1) What are some good ways to define what capacity represents from a memory standpoint?
...the (contiguous?) memory allocated to the ArrayList?
Yes, an ArrayList is backed up by an array, to that represents the internal array size.
...the ArrayLists’s memory footprint on the (heap?)?
Yes, the larget the array capacity, the more footprint used by the arraylist.
2) Then if the above is true, changing capacity requires some manner of memory management overhead?
It is. When the list grows large enough, a larger array is allocated and the contents copied. The previous array maybe discarded and marked for garbage collection.
3) Anyone have an example where #2 was or could be a performance concern? Aside from maybe a large number of large ArrayLists having their capacities continually adjusted?
Yes, if you create the ArrayList with initial capacity of 1 ( for instance ) and your list grows way beyond that. If you know upfront the number of elements to store, you better request an initial capacity of that size.
However I think this should be low in your list of priorities, while array copy may happen very often, it is optimized since the early stages of Java, and should not be a concern. Better would be to choose a right algorithm, I think. Remember: Premature optimization is the root of all evil
See also: When to use LinkedList over ArrayList

adding to the middle of an empty ArrayList?

if I create a new arraylist of size 5...
Player P;
ArrayList<Player> orderedPlayers = new ArrayList<Player>(5);
and then I try to add to the middle of that arraylist...
orderedPlayers.add(2, P);
I get an indexoutofbounds... I also get indexoutofbounds if I use set instead of add...
orderedPlayers.set(2, P);
in fact the only way I can add P to the arraylist is if I use the 0 index...
orderedPlayers.add(0, P);
and also for some strange reason when I do that my debugger in eclipse sees that element added to the 4th index of orderedPlayers instead of the 0th... is ArrayList buggy or am I completely missing something? how would I add to the middle of a null ArrayList?
The 5 is the initial capacity, not the actual size. You can't add to the middle of an empty array list.
Here is probably what you want to do in order to initialize orderedPlayers:
ArrayList<Player> orderedPlayers =
new ArrayList<Player>(Collections.nCopies( 5, null ));
Then you have a list with 5 null elements, at this point you can insert in the middle of it.
When you create an ArrayList with a number in parameter, this number will be used to set the initial capacity. That way the List won't need to create a new array for "every" call to add(). If you can tell that your List will contain 100 elements, you can use new ArrayList(100). That doesn't mean that the 100 elements exists or are accessible.
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.
ArrayLists are dynamic structures... if you want to be able to add stuff at specific locations, you might have to use an array instead.
you may initialize your array list by NULL objects in a loop.
or even if the size is fixed. then use Array instead of List.
You seem to be under the mistaken impression that when you write new ArrayList<Player>(5), you're getting something similar to a 5-element array. You aren't. You're getting an empty list that happens to be backed by an internal array that can initially hold up to 5 elements. The list itself, however, has no elements at all.
Lists are dynamic and grow and shrink as elements are added to them and removed from them. You start out with 0 elements. If you then add 5 players, the list will have 5 elements. If you just use the normal add(T) method with no index, you'll end up with the elements in the order they were added.
By constructing an ArrayList with an initial capacity ArrayList(int initialCapacity), you are indicating roughly how large the list can get before Java will increase its size.
You are not allocating slots, as in an array. The ArrayList's size is based on the number of elements in the list, and you cannot insert or set a value to an index greater than its size.

Categories

Resources