How to fill an array with a vararg with repeat? - java

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);
}

Related

Need help using java.lang.reflect.Array to sort arrays

An interview question was to write this method to remove duplicate element in an array.
public static Array removeDuplicates(Array a) {
...
return type is java.lang.reflect.Array and parameter is also java.lang.reflect.Array type.
How would this method be called for any array?
Also not sure about my implementation:
public static Array removeDuplicates(Array a)
{
int end=Array.getLength(a)-1;
for(int i=0;i<=end-1;i++)
{
for(int j=i+1;j<=end;j++)
{
if(Array.get(a, i)==Array.get(a, j))
{
Array.set(a, j, Array.get(a, end));
end--;
j--;
}
}
}
Array b=(Array) Array.newInstance(a.getClass(), end+1);
for(int i=0;i<=end;i++)
Array.set(a, i, Array.get(a, i));
return b;
}
You may want to consider using a different data structure such as a hashmap to detect the duplicate (O(1)) instead of looping with nested for loops (O(n^2)). It should give you much better time complexity.
There are various problem with this code. Starting here:
if(Array.get(a, i)==Array.get(a, j))
Keep in mind that those get() calls return Object. So, when you pass in an array of strings, comparing with == simply will most likely result in wrong results (because many objects that are in fact equal still have different references --- so your check returns false all the time!)
So, the first thing to change: use equals() instead of == !
The other problem is:
end--;
Seriously: you never ever change the variable that controls your for loop.
Instead: have another counter, like
int numberOfOutgoingItems = end;
and then decrease that counter!
For your final question - check the javadoc; for example for get(). That reads get(Object array, int index)
So you should be able to do something like:
int a[] = ...;
Object oneValue = Array.get(a, 0);
for example.
Disclaimer. I have to admit: I don't know if the Array implementation is smart enough to automatically turn the elements of an int[] into an Integer object.
It could well be that you have to write code first to detect the exact type of array (if it is an array of int for example); to instead call getInt() instead of getObject().
Beyond that, some further reading how to use reflection/Array can be found here

how to write generic method for expand capacity of array?

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.

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

Where is Java's Array indexOf?

I must be missing something very obvious, but I've searched all over and can't find this method.
There are a couple of ways to accomplish this using the Arrays utility class.
If the array is not sorted and is not an array of primitives:
java.util.Arrays.asList(theArray).indexOf(o)
If the array is primitives and not sorted, one should use a solution offered by one of the other answers such as Kerem Baydoğan's, Andrew McKinlay's or Mishax's. The above code will compile even if theArray is primitive (possibly emitting a warning) but you'll get totally incorrect results nonetheless.
If the array is sorted, you can make use of a binary search for performance:
java.util.Arrays.binarySearch(theArray, o)
Array has no indexOf() method.
Maybe this Apache Commons Lang ArrayUtils method is what you are looking for
import org.apache.commons.lang3.ArrayUtils;
String[] colours = { "Red", "Orange", "Yellow", "Green" };
int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");
For primitives, if you want to avoid boxing, Guava has helpers for primitive arrays e.g. Ints.indexOf(int[] array, int target)
There is none. Either use a java.util.List*, or you can write your own indexOf():
public static <T> int indexOf(T needle, T[] haystack)
{
for (int i=0; i<haystack.length; i++)
{
if (haystack[i] != null && haystack[i].equals(needle)
|| needle == null && haystack[i] == null) return i;
}
return -1;
}
*you can make one from your array using Arrays#asList()
Unlike in C# where you have the Array.IndexOf method, and JavaScript where you have the indexOf method, Java's API (the Array and Arrays classes in particular) have no such method.
This method indexOf (together with its complement lastIndexOf) is defined in the java.util.List interface. Note that indexOf and lastIndexOf are not overloaded and only take an Object as a parameter.
If your array is sorted, you are in luck because the Arrays class defines a series of overloads of the binarySearch method that will find the index of the element you are looking for with best possible performance (O(log n) instead of O(n), the latter being what you can expect from a sequential search done by indexOf). There are four considerations:
The array must be sorted either in natural order or in the order of a Comparator that you provide as an argument, or at the very least all elements that are "less than" the key must come before that element in the array and all elements that are "greater than" the key must come after that element in the array;
The test you normally do with indexOf to determine if a key is in the array (verify if the return value is not -1) does not hold with binarySearch. You need to verify that the return value is not less than zero since the value returned will indicate the key is not present but the index at which it would be expected if it did exist;
If your array contains multiple elements that are equal to the key, what you get from binarySearch is undefined; this is different from indexOf that will return the first occurrence and lastIndexOf that will return the last occurrence.
An array of booleans might appear to be sorted if it first contains all falses and then all trues, but this doesn't count. There is no override of the binarySearch method that accepts an array of booleans and you'll have to do something clever there if you want O(log n) performance when detecting where the first true appears in an array, for instance using an array of Booleans and the constants Boolean.FALSE and Boolean.TRUE.
If your array is not sorted and not primitive type, you can use List's indexOf and lastIndexOf methods by invoking the asList method of java.util.Arrays. This method will return an AbstractList interface wrapper around your array. It involves minimal overhead since it does not create a copy of the array. As mentioned, this method is not overloaded so this will only work on arrays of reference types.
If your array is not sorted and the type of the array is primitive, you are out of luck with the Java API. Write your own for loop, or your own static utility method, which will certainly have performance advantages over the asList approach that involves some overhead of an object instantiation. In case you're concerned that writing a brute force for loop that iterates over all of the elements of the array is not an elegant solution, accept that that is exactly what the Java API is doing when you call indexOf. You can make something like this:
public static int indexOfIntArray(int[] array, int key) {
int returnvalue = -1;
for (int i = 0; i < array.length; ++i) {
if (key == array[i]) {
returnvalue = i;
break;
}
}
return returnvalue;
}
If you want to avoid writing your own method here, consider using one from a development framework like Guava. There you can find an implementation of indexOf and lastIndexOf.
Java ArrayList has an indexOf method. Java arrays have no such method.
I don't recall of a "indexOf" on arrays other than coding it for yourself... though you could probably use one of the many java.util.Arrays#binarySearch(...) methods (see the Arrays javadoc) if your array contains primitive types
The List interface has an indexOf() method, and you can obtain a List from your array with Array's asList() method. Other than that, Array itself has no such method. It does have a binarySearch() method for sorted arrays.
Arrays themselves do not have that method. A List, however, does:
indexOf
You're probably thinking of the java.util.ArrayList, not the array.
There is no direct indexOf function in java arrays.
Jeffrey Hantin's answer is good but it has some constraints, if its this do this or else to that...
You can write your own extension method and it always works the way you want.
Lists.indexOf(array, x -> item == x); // compare in the way you want
And here is your extension
public final class Lists {
private Lists() {
}
public static <T> int indexOf(T[] array, Predicate<T> predicate) {
for (int i = 0; i < array.length; i++) {
if (predicate.test(array[i])) return i;
}
return -1;
}
public static <T> int indexOf(List<T> list, Predicate<T> predicate) {
for (int i = 0; i < list.size(); i++) {
if (predicate.test(list.get(i))) return i;
}
return -1;
}
public interface Predicate<T> {
boolean test(T t);
}
}
int findIndex(int myElement, int[] someArray){
int index = 0;
for(int n: someArray){
if(myElement == n) return index;
else index++;
}
}
Note: you can use this method for arrays of type int, you can also use this algorithm for other types with minor changes

Categories