how to write generic method for expand capacity of array? - java

I want write a generic method to expand the capacity of the array that with specific type. The function signature may like this(not have to), the parameter "growth" means the number of growing capacity.
public static T[] expandCapacity(T[] array, int growth)
The example: Integer[] testArray = new Integer[5];
testArray = expandCapacity(testArray,5);
after executed this function, the testArray.length should be 10.

To use a generic type T with a static method you must specify it with a <T>. Then you could use Arrays.copyOf(T[], int) which (per the Javadoc) copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length.
public static <T> T[] expandCapacity(T[] array, int growth) {
return Arrays.copyOf(array, array.length + growth);
}

If you want to change the length of the original array, which means the return array of expandCapacity is the same reference as the parameter array, it's impossible because an array has a fixed length after its initialization.
If the return array isn't the same reference, just create a new array with the new size inside the method and copy the data from the source array, but I'm afraid it's not what you want.
I suggest you look into List<E> interface as well as its implementations like ArrayList<E> whose size can be changed.

Related

How to fill an array with a vararg with repeat?

I'm looking for an algorithm to fill an array of a specific size with the contents of a vararg, repeating the last element of the vararg until the array is full.
public static <T> T[] fillWithRepeat(int length, T... elements) {
// make array of length "length" and fill with contents of "elements"
}
Does anyone know a good algorithm for this?
As the question doesn't include any attempt of solving the problem itself, I assume homework, thus the answer is pseudo code only:
create a new array results of length length
iterate index from 0 to length
establish an index2 variable that runs from 0 to elements.length
assign ressult[index] = elements[index2]
either increase index2, or when it reaches elements.length-1, keep it at that value
For creating a "generic" array, see here.
And of course, user Hulk is correct (again), there are utility methods Arrays.fill() and for newer Javas Array.copyOf() that you should consider using.
Here's the algorithm. It also caters for the Generic instantiation problem when you will need to instantiate an array of type T
public static <T> T[] fillWithRepeat(int length, T... elements) {
List<T> output = new ArrayList<>(Arrays.asList(elements));
for(int i = 0; i < length - elements.length; i++){
output.add(elements[elements.length - 1]);
}
return output.toArray(elements);
}

Java method to return random element of array of different types

I would like to pass different arrays of changing parameter types at different times into a method/function of which randomly returns one element, however am extremely struggling to do so using Java.
I have attempted to do so using the following code:
public int rndInx(Array theArray) {
theArray = theArray[(int)(Math.random() * theArray.length)];
return theArray;
}
However, Eclipse draws attention to errors; length not being resolved and the type of expression must be an array type. I assume one cause of the issue is the returnType, however I'm unsure what type would accept a range of returnTypes. I am aware that the syntax is probably extremely wrong too since I've only recently began to learn Java :(
For example, if I was to pass an array containing integers, then one random integer element would be returned - and if I was to pass an array containing strings etc. than one random element from the array in question would be returned.
Thanks in advance.
Here are the steps to achieve your end goal.
overload the method rndInx for int[] parameter, double[], long[] and so forth for however many primitive types you need to consider.
create a generic method for reference types
here is a hint for the generic method:
public <T> T rndInx(T[] theArray) {
return theArray[....]; // return the element at a random index
}
You can use a generic method:
public <T> T rndInx(T[] array) {
int index = (int)(Math.random() * array.length);
return array[];
}
But this won't work for primitive arrays. If you must accept primitive arrays, you'll have to use reflection and hope the caller has the right type:
public <T> T rndInx(Object array) {
int index = (int)(Math.random() * Array.getLength(array));
return (T)Array.get(array, index);
}
Or return Object and let the caller do the casting.
What you want is to use generics, e.g. like this:
public <T> T selectOneRandomly(T[] array) {
return array[(int)(Math.random() * array.length)];
}
This should work for anything except primitives like int, double etc.
For those you'd either have to provide special methods via overloads (e.g. int selectOneRandomly(int[] array)) or convert the arrays of primitives to arrays of wrapper types (i.e. int[] to Integer[]) before passing the converted arrays to your method.

Making a variable length array of ints

I want to have a array of integers where the length is variable. The obvious choice is to use ArrayList but can I do this for primitive types such as
ArrayList<int> myArray=new ArrayList<int>();
I dont want to use
ArrayList<Integer>
because the Integer class is clumsy in terms of coding.
EDIT: From the answers below I think the solution is to write my own Integer class.
To answer the question below about "clumsy" let me give a specific, and I would of thought common use for integers namely using the last member of the array in any place you would want the integer. If I just call the array "name" then to get the actual integer that can be operated on I need
name.get(name.size()-1).intValue();
To me this seems like an awfully unwieldy expression for a simple integer - particularly if it appears in an expression twice. It also seems that (most of the) methods available for the Integer class are absolutely redundant. Take two examples
static int compare(int a, int b)
Quite unbelievably, according to the documentation, this method returns a-b!!
static Integer valueOf(int a)
returns an Integer instance of the integer a. Can someone give me a single example where
new Integer(a)
does not achieve exactly the same result?
Method 1: (not recommended)
You can do something like this, but this doubles the code and is not efficient:
int[] a;
//get size (from command line maybe ow whatever method you want)
You can set size 0 initially, and for ex. you are transferring values from arraylist so you will have to write:
while(itr.hasNext()){
size++;} //itr is an object of Iterator
int i=0;
a=new int[size];
// then loop again to store values
while(itr.hasNext()){
a[i]=itr.next();
i++;}
Method 2:
Or you may use ArrayList without making it clumsy as follows:
ArrayList al=new ArrayList();
then you may declare Integer objects as volatile and perform operations on them just as you do with the primitive types.
Method 3: (not recommended)
Or simply write:
ArrayList al=new ArrayList();//ignore the warning about <E>
int x=2;
al.add(2);
Method 4: (recommended)
If I were you I would use ArrayList<Integer>.
UPDATE: Another thing that might work is that you may initially create an ArrayList<Integer> and store values there and later convert it to int[]
This SO answer tells about the conversion. Quoted the code form there:
public static int[] convertIntegers(List<Integer> integers)
{
int[] ret = new int[integers.size()];
for (int i=0; i < ret.length; i++)
{
ret[i] = integers.get(i).intValue();
}
return ret;
}
Hope this helps.
No it's not possible to use primitive types as generic type.
Well I would recommend you do use ArrayList and avoid primitive types in this case.
You can't change the size of an array once created. You have to allocate it bigger than you think you'll ever need
or
Accept the overhead of having to reallocate it to a new larger array and copy the data from the old to the new:
System.arraycopy(oldItems, 0, newItems, 0, 10);
But Much simpler to go with ArrayList.

Select subarray without copying into new buffer?

I have float[] array of length 100. Is there a way I can select (pseudocode):
x = array[10:19];
To get elements 10,11,12,...,19 without copying over into another buffer? I'm in a mobile application where I don't want to waste space or time doing this. I'd rather just reference the pointers the system uses for array.
The most efficient way to do this would be to use System.arrayCopy(), which is much faster and more efficient than copying manually using a loop. It will require another array, but any approach you use (beyond just passing the original array around with a couple of ints representing the offset to use) will do this, and it's relatively cheap - the memory consuming bit is usually the objects that it's referencing rather than the array itself, and they are not copied.
No, there is no API to do that. The closest solution to this would be building your own class that wraps an existing array, and does the re-indexing:
class SubArray {
private final float[] data;
private final int offset;
private final int length;
public SubArray(float[] data, int offset, int length) {
this.data = data;
this.offset = offset;
this.length = length;
}
public float get(int index) {
if (index >= length) throw ...
return data[index + offset];
}
public void set(int index, float value) {
if (index >= length) throw ...
data[index + offset] = value;
}
}
If the result that you need is a new object that behaves like an array in all respects, including the indexing operator, you would need to make a copy.
(Update) Precondition: You should store the data in a Float[] instead of a float[], the performance-hit should be minimal.
You can use: Arrays.asList(array).subList(10, 20).
The Arrays.asList(array) does the following:
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray(). The returned list is serializable and implements RandomAccess.
Source
And then .subList(10, 20) returns you a List.
Then if you really want to work with arrays in the end, you could take the following lines:
List<Float> subList = Arrays.asList((Float[])array).subList(10, 20);
Float[] subArray = subList.toArray(new Float[subList.size()]);
(Update) Changed Arrays.asList(array) to Arrays.asList((Float[])array) such that it is correct now.
From documentation:
Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.
If the list fits in the specified array with room to spare (i.e., the array has more elements than the list), the element in the array immediately following the end of the list is set to null. (This is useful in determining the length of the list only if the caller knows that the list does not contain any null elements.)
Like the toArray() method, this method acts as bridge between array-based and collection-based APIs. Further, this method allows precise control over the runtime type of the output array, and may, under certain circumstances, be used to save allocation costs.
Suppose x is a list known to contain only strings. The following code can be used to dump the list into a newly allocated array of String:
Source
This should ensure that no data is wasted, the only thing to be careful about could be autoboxing.
UPDATE: Changed my answer such that it now is correct under a precondition.
What is the problem of using a simple for loop? Objects are in java called by reference.
So, executing copying the array does not copy the objects.
float[] subarray = new float[10];
for(int i = 10, j = 0; i < 19; i++, j++) {
subarray[j] = x[i];
}
The array[0] is a reference to the object of x[0].
edit: This only applies for objects, and i don't know if it also applies to a float

How to 'remove' an Object from a Java array (can't use Collections)

As a sample, I am developing a simple MySortedSet in java which implements SortedSet interface. It is backed up with a simple array which is E[] array.
I have several questions regarding that:
This is the class: (I am not writing entire code, instead of related parts)
public class MySortedSet<E> implements SortedSet<E>, Iterator<E> {
private E[] array;
private Comparator<? super E> _comparator;
private int size = 0;
private int capacity;
#SuppressWarnings("unchecked")
public MySortedSet() {
this.capacity = 10;
this.array = (E[]) new Object[this.capacity];
// this.array = Array.newInstance(Class<E> var,int size);
// We have to get Class<E> from outside caller.
}
}
Since it accepts all sort of type from primitive to reference types etc. I am not really sure when removing an item, assigning null is a good way in place of the removed item. Since Java initializes primitive types with 0. So null only works for reference types.
Below is probably very bad design:
#Override
public boolean remove(Object o) {
int indexOfElement = this.find(o);
boolean removed = false;
if (indexOfElement != -1) {
this.array[indexOfElement] = null;
removed = true;
}
return removed;
}
Can someone tell me what the best way is to remove an element from an array?
Edit:
Honestly what I am thinking to remove an element from an simple array is like copy the entire array without the removed item into a whole new array but I am not sure how efficient it would be in terms of performance and etc.
It kinda depends on the context of how you want to use your array. For example, if you are going to be iterating over the array and using the contents of it for standard methods like Arrays.sort(), they might generate NullPointerExceptions if you have null values in your array.
If you really want to remove items from an array in a safe way, I'd suggest changing your array to an ArrayList like this...
ArrayList<Object> list = new ArrayList<Object>();
list.add(object);
list.remove(object);
As this will actually remove the item from the list completely - no nulls or anything will remain, and performing methods like length() will return a real value.
For instances when I have used an array, I set the value to null, and ensure that all iterations over the array check that value != null before I try to query it. After setting the nulls for the removed items, I usually loop over the array and manually sort all the nulls to the end of the array, and then do System.arraycopy() to resize the array. This will leave you with a new array of the correct size, with all items in it except for the removed ones. However, I suggest this only if you really must use an array, as it is slower and introduces much greater potential for errors and NullPointerExceptions.
Alternatively, if you're not worried about sort-order, you can simple move the last item in the array over the top of the item you want to remove, and keep a count of the real array size. For example...
Object[] array = new Object[20];
int realSize = 15; // real number of items in the array
public void remove(int arrayIndex){
array[arrayIndex] = array[realSize-1];
realSize--;
}
This method removes an item in the array by 'replacing' it with the item in the last position of the array - its very quick and pretty to implement, if you don't care about sort order.

Categories