How can I pass arrays in Java where I can indicate a different start index (0th index) for the array argument. In C++, you can pass arrays like this
myMethed(myArray + 3); // passing method where begin index is 4th element
...
void myMethod(int* arr) {
int val = arr[0]; // refers to the 4th element
int val2 = arr[1]; // 5th element
}
How can I do something similar in Java. I tried copying a subset of the array using Arrays.copyOfRange but I don't want a separate copy but the same array with a different start index.
Of course I can do this:
myMethod(int[] arr, int startIndex) {
int val = arr[startIndex];
int val2 = arr[startIndex + 1];
}
But are there other ways without declaring a separate parameter for start index?
Thanks a lot.
but the same array with a different start index.
In Java, an array is an object whose size is defined at the point it is initialized. The starting index is always zero and the size is fixed. These two cannot be altered after memory has been allocated. In Java same array means same object and not a memory space.
Java doesn't allow you to slice the allocated memory as a new array. So, you will always need to create another array, or explicitly pass the starting index to the method you are calling.
In general, prefer collections over arrays. Your particular need can be solved by using Lists instead:
myMethod(List<Integer> list) {
int val = list.get(0);
int val2 = list.get(1);
}
...
List<Integer> myList = ...;
myMethod(myList.subList(3, myList.size()));
From the List.subList documentation:
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
(emphasis mine)
You can create an iterator, move it to the required position and pass it as a method argument.
what about this ?
Integer myarr[] = new Integer[] { 1, 2, 3, 4 };
System.out.println(Arrays.toString(Arrays.asList(myarr).subList(2, myarr.length).toArray(new Integer[2])));
Related
I need to remove only one occurence of an integer in a ArrayList of integers. My code right now removes all integers with a specific value.
list.removeIf(s -> s.equals(data));
If I have for example:
ArrayList<Integer> i = new ArrayList<Integer>();
i.add(1);
i.add(1);
i.add(3);
i.add(5);
and I want to remove only the first 1 or the second 1. Not both.
Solution
Use the List#remove method. That is exactly what it was made for, from the documentation:
Removes the first occurrence of the specified element from this list, if it is present (optional operation). If this list does not contain the element, it is unchanged. [...]
boolean wasRemoved = list.remove(data);
Removing ints
However, you might have a minor issue here. Your data type is Integer and data is probably of type int. And there is already a method with the signature List#remove(int) (documentation) which will remove the element at the given index, not the element itself.
You can bypass this by explicitly boxing your data to an Integer, which is what you actually have stored in the list:
boolean wasRemoved = list.remove((Integer) data);
Or directly make the data variable of type Integer instead of int.
Just use remove method from the list.remove(new Integer(data)), by the implementation you can see that it removes the first element then exits:
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
I'm looking for a way to cut a initial array from a specific index to another index
int[] array = {10,5,4,4,3,5,6};
int[] arrayCopy;
In this example, if I want to segment from index[1] to index[4]. The new array witch I store in arrayCopy should looks like this one arrayCopy[] = {5,4,4,3}. The constante problem is that my objectif is to keep reference of the original array.So if in arrayCopy I change a element il will change too in array
arrayCopy[] = {5,4,4,3}
arrayCopy[0] = 20 // arrayCopy[] = {20,4,4,3} and array = {10,20,4,4,3,5,6};
I tried Arrays.copyOfRange() but it's a deep copy and System.arraycopy() make a shallow copy but it doesn't accomplish what I want.
I tried to make my own method
public E[] fillArray(int[] _array, int begin, int end){
int[] arrayTemp;
for ( int i = begin ; i <= end; i++ ) {
arrayTemp[i] = _array[i];
}
return arrayTemp;
}
Output
arrayCopy = fillArray(array,1,4);
Exception in thread "main" java.lang.NullPointerException
Note: I want to keep the array mechanism and not using an ArrayList or ...
Can I change the second array and the first array will change too?
There is no way for Java arrays to support that feature.
A Java array is an Object, so all arrays are independent objects, with their own memory structure for the array values.
(This is unlike C, where an array is done by pointer manipulation, so a second pointer can point into the memory sequence of an array already referenced by another pointer.)
If you want a sub-array of the first array, that is mapped such that changes to the sub-array is reflected in the main array, and vice-versa, you need something else.
One option is to use a List, and create the sub-list using subList(int fromIndex, int toIndex):
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.
If you already have an array, you can wrap the array with a list using Arrays.asList(T... a), then use the subList() as for any other list.
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)
Note that List doesn't work for primitive types, so if your array is a primitive, you should use a Buffer of the appropriate type ( ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer).
E.g. for an int[], create the buffer using IntBuffer.wrap(int[] array, int offset, int length):
Wraps an int array into a buffer.
The new buffer will be backed by the given int array; that is, modifications to the buffer will cause the array to be modified and vice versa.
If you always access the array through the IntBuffer, by using IntBuffer.wrap(int[] array) to wrap the full array, your code could use either IntBuffer and not know if it is accessing the full array or the sub-array.
This should work.
public static int[] fillArray(int[] _array, int begin, int end){
int[] arrayTemp = new int[end-begin+1];
for ( int i = begin ; i <= end; i++ ) {
arrayTemp[i-begin] = _array[i];
}
return arrayTemp;
}
On creating an arrayList using the below mentioned code snippet:
List arrayList = new ArrayList(16);
The internal implementation of ArrayList creates an array elementData of size 16 and assigns nullat every location. On doing something like arrayList.add(2,"HelloWorld") gives an IndexOutOfBoundException as the index at which the element is being added (i.e 2) is greater than the size attribute of the arrayList .
As clear from the javaDocs, the size attribute of the arrayList is initialized to 0 when the arrayList is initialized and is incremented by 1 everytime a new element is added to the arrayList
Can someone please explain, why the ArrayList dataStructure was designed this way in the first place. Even tho' the internal dataStructure elementData was initialized with 16 null values at the creation of arrayList, still it does not allow to add value at indeces > size; (assuming index <16 in this case). What was the idea to implement the add(index,object)
funtionality to be governed by the size attribute of the arrayList?
The purpose of having an internal array with a size greater then List.size() is to avoid re-allocating the array unnecessarily. If the internal array always had the same size as the List, then every time a new element is added, the internal array would have to be re-allocated, causing a performance penalty.
In fact, the default constructor of ArrayList constructs a list with an initial capacity of 10.
public ArrayList() {
this(10);
}
But why we need such an allocation? As you understand, if you indicate the size of ArrayList in advance, you can provide efficient for the list. Otherwise, after the number of elements exceeds the initial capacity of ArrayList, a new reallocation operation is performed for each element.
The documentation says:
public void add(int index, E element)
Throws:
IndexOutOfBoundsException -
if the index is out of range
(index < 0 || index > size())
As you can see, it throws IndexOutOfBoundsException if (index > size()).
Since ArrayList's "public int size()" returns elements which are not equal to null, your size equals to 0 (not 16 as you said in your example). In other words, if null values were counted as well, the size of each ArrayList that was created with default constructor would be 10.
Consequently, "arrayList.add(2, "HelloWorld")" throws IndexOutOfBoundsException since index = 2 but size() = 0.
Edit:
I think when you mount your argument, you use this as base:
String[] arr = new String[5];
arr[3] = "hello";
System.out.println(arr[3]);
Then, you think why you can give a value in an array element directly but why you cannot do the same thing while using add(int index, E element) method of ArrayList. Actually, it is true but there is no condition to implement ArrayList as complete counterpart of Array. In other words, this method is conditioned with that rule since it is nature of ArrayList. As we all know, when you create an array, you specify its size in square brackets. The constructor of ArrayList which takes int as parameter does not do the same thing. It performs just an imaginary allocation. Yes, it could specify its initial size with this allocation or after add(int index, E element) is called, size could be increased by one. However, ArrayList is implemented to provide an array-like structure which has continuity with respect to index number but has no fixed size. Thence, there are some other higher level of abstraction examples do this task. To exemplify, LinkedHashMap structure.
You can not add object at a specific index till it contains null. You just need to add object using add method and then you can update values on a index.
For Example.
ArrayList<Integer> arrlist = new ArrayList<Integer>(5);
// use add() method to add elements in the list
arrlist.add(15);
arrlist.add(22);
arrlist.add(30);
arrlist.add(40);
// adding element 25 at third position
arrlist.add(2,25);
You rarely need to specify the capacity of an ArrayList, it can improve the performance only if you know how many elements your ArrayList will hold.
ArrayList is simply a List that can automatically be grown or shrink. Using List, you never need to add an element in the place n if the list is empty, you simply link it to the previous node (unless it's the head of course) - that's the idea of ArrayList except the fact that it can be grown/shrink automatically.
See the java doc of ArrayList's add(int index,
E element) method. Here you can find the ArrayIndexOutOfBound exception occurred when if the index is out of range (index < 0 || index > size()).
You declared an ArrayList with an initial capacity 16. It doesn't mean that each of the 16 indexed position of the ArrayList contains element. It just mention the initial capacity and when it necessary it will grow it's size dynamically.
See the source code the constructor from the ArrayList class -
/**
* Constructs an empty list with the specified initial capacity.
*
* #param initialCapacity the initial capacity of the list
* #exception IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
Here we can not find anything that told us - ArrayList will initiated with null value.
Update: Based on your comment I have done some experiment, since I'm not sure about whether an array of reference/non-primitive type will initialized with null. See the following code below. Run the the code by uncommenting each of line at per execution -
import java.util.List;
import java.util.ArrayList;
public class ArrayListTest{
public static void main(String[] args){
List<String> list1 = new ArrayList<String>(); //default with initial capacity 10
List<String> list2 = new ArrayList<String>(5);
List<String> list3 = new ArrayList<String>(5);
list2.add(null);
list2.add(null);
list2.add(null);
list3.add("zero");
list3.add("one");
list3.add("two");
//System.out.println(list1.get(4)); //IndexOutOfBoundException
//System.out.println(list2.get(0)); //null
//System.out.println(list2.get(2)); //null;
//System.out.println(list2.get(3)); //IndexOutOfBoundException
//System.out.println(list3.get(0)); //zero
//System.out.println(list3.get(2)); //two;
//System.out.println(list3.get(3)); //IndexOutOfBoundException
//list3.add(4, "four"); //IndexOutOfBoundException
}
}
Here you can see list2.get(0) and list2.get(2) gives you null. Because we put null at these index. But list2.get(3) doesn't give null since we didn't put null at index 3. So it seems array of reference/non-primitive type won't initialize with null. list2.get(3) gives IndexOutOfBoundException.
You found the same scenario for the list3. where I didn't put any null in this list. Even when we are trying to add some value at index 4 of list3 it gives IndexOutOfBoundException. Since the index 4 is not available for the list3. But you can add some value at index 2 of list2. Cause at index 2 of this list I have inserted null manually.
So in long story short (I think) - new ArrayList<SomeType>(givenSize) wouldn't initialize an array with givenSize with all element setting to null.
Hope it will Help.
Thanks.
The question is pretty much as stated in the title. I'm in an algorithms course and the professor and I disagree regarding whether or not operations performed on an ArrayList sublist (a sublist generated by ArrayList.sublist) can be considered 'in place'. To my read of the Java API:
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations.
you are still manipulating the 'master' ArrayList directly. To his view, you are copying references from the 'master' array into a new sub-array which means employing ArrayList.subList is not considered 'in place'. Obviously, for the purposes of the course what he says goes (that is, if I want to pass :-/) but I would like to know either way for my own growth as a programmer. Code is below - and thank you!
public static int findK (int findME, int mVal, ArrayList<Integer> arr) {
// pre stage return variable
int returnVal = -1;
// make a subarray consisting of indexes 0 - ((m-2)+(m-1)).
// this because the relationship between the m, p, and q
// is p>q>m - therfore the max value of q is m-1 and the
// max value of p is m-2.
int newArrSize = (mVal-2) + (mVal-1);
ArrayList<Integer> subArr = new ArrayList<Integer>(arr.subList(0, newArrSize));
// make the list smaller by looking at only the last [mVal]
// elements. this because we know what we're looking for
// has to be in the second section of the array, and that
// section can't possibly be larger than mVal
int fromIndex = subArr.size() - mVal;
subArr = new ArrayList<Integer> (subArr.subList(fromIndex, subArr.size()));
// at this point we can do a simple binary search, which on an
// a sorted array of size mVal is lg(m)
while (subArr.size() > 1) {
// get midpoint value
int midPointIndex = subArr.size() / 2;
int midPointValue = subArr.get(midPointIndex);
// check for case where midpoint value is in the first
// region of the array
// check for case where the midpoint is less than the
// findME value
//
// if true, discard first half of the array
if ((midPointValue == 9000) || (midPointValue < findME)) {
subArr = new ArrayList<Integer> (subArr.subList(midPointIndex, subArr.size()));
continue;
}
// else if midpoint is less than findMe, discard the second
// half of the array
else if (midPointValue > findME) {
subArr = new ArrayList<Integer> (subArr.subList(0, midPointIndex));
continue;
}
// if we're here, we've found our value!
returnVal = midPointValue;
break;
}
// check for match and return result to caller
// only perform check if we haven't already found the value
// we're looking for
if (returnVal == -1) returnVal = (subArr.get(0) == findME) ? (subArr.get(0)) : (-1);
return returnVal;
}
I assume in this answer, that by "in place" actually "uses constant additional memory" is meant.
The sublist function creates a view of the original list. This uses only O(1) memory.
However you allocate a new list (Indices were replaced with my own names here, for simplicity):
subArr = new ArrayList<Integer> (subArr.subList(index1, index2));
What you do with such a statement is:
create a subList view (uses O(1) memory)
copy the sublist (uses O(sublist size) = O(index2 - index1) memory).
delete reference to subList (and by that the reference to the old list too)
Note that the garbage collector can not claim the memory of the old list until all references to it are deleted. The sublist view contains a reference to the old list, so the old list cannot be claimed by the GC until all references to the sublist view are deleted. This means for a short while you use O(index2 - index1) more memory than in the list at the beginning. Since binary search makes the list half as large in every step, you use O(subArr.size()) additional memory (not in O(1)).
Lines like these:
subArr = new ArrayList<Integer> (subArr.subList(fromIndex, subArr.size()));
That's your "copy". The new ArrayList is indeed, a copy of the data from the subList.
If you were using the subList "raw", then it could be better argued that you are "in place", because then the subList is simply a set of offsets in to the original array.
But with the create of new ArrayLists, you are definitely copying.
Of course, the easiest way to check is that when you find your value, change the value in the list to some sentinel (9999 or whatever). Then dump your original list. If 9999 shows up, it's in place. If not, then, it's not.
"In-place" isn't a term that applies to binary-search, as it almost always refers to how modifications are made (e.g. for sorting, like quicksort (in-place) and mergesort (not in-place)). So it's not something you need to worry about for binary search, as searching makes no modifications.
As for whether ArrayList#subList() copies data, a look at the source code should prove that that is incorrect. Unfortunately, the source is a tad long for a SO answer, but I'll do my best to summarize.
The subList() method is this:
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
Where SubList is defined as the inner class:
private class SubList extends AbstractList<E> implements RandomAccess
with instance fields
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
Note how none of those fields are a type of array or list.
Looking at the implementations of mutators shows that all work is delegated to the parent class. For example, here is set():
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
Notice how ArrayList.this is used to refer to the containing ArrayList instance, which means that the source ArrayList implementation is modified and not any (nonexistent) copy.
The add() method shows something similar:
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
}
parent.add() is used here, where parent is also the containing instance. So again, it is the source list that is modified, and not any (nonexistent) copy.
And so on and so forth.
However, as pointed out by Will Hartung, all this is moot if you pass the resulting SubList into the constructor of a new ArrayList<>(), as the constructor:
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray(); // <------------ This line
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
makes a copy of the internal array (through toArray()), which is the copy your professor/TA were likely talking about.
ArrayList<String> newArray = new ArrayList<String>();
newArray = urlList.getUrl();
for( int i = 0 ; i < newArray.size();i++)
{
System.out.println(newArray.get(i));
}
newArray.toArray(mStrings );// is this correct
mStrings = newArray.toArray();// or this to convert ArrayList ot String array here
for( int i = 0 ; i < mStrings.length;i++)
{
System.out.println(mStrings[i]);
}
EDIT: when i try as below, I get null pointer exception:
try
{
newArray.toArray(mStrings );
for(int i = 0 ; i < mStrings.length; i++)
{
System.out.println(mStrings[i]);
}
} catch( NullPointerException e )
{
System.out.println(e);
}
Usually I write
String[] array = collection.toArray(new String[collection.size()]);
because this way
I get an array of the type that I want.
I don't have to declare the array before calling Collection.toArray(T[]).
Depends on what you want to do. Both are correct
toArray()
Returns an array containing all of the elements in this list in proper sequence (from first to last element).
Refer here
toArray(T[] a)
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.
Refer here
In former, you want to get an array. In latter you have an array, you just wanted to fill it up.
In your case, first form is preferred as you just want to get an array without bothering size or details.
Basically this is what happens in 2nd case:
List's size is measures.
(a) If list size is less than that of the array provided, new Array of the type provided as argument is created.(b)Else, the list is dumped in the specified array.
The only benefit of doing so, is you avoid casting. The two form are the same. If you use Object array. i.e.
myList.toArray() <==> toArray(new Object[0])
Now, If you pass an uninitialized array, you will get a NullPointerException. The best way to do it is:
String[] y = x.toArray(new String[0]);
Please read the document
The first option is better as it allows you to pass in a typed array, which is then populated inside the method.
The second option returns an Object[] - so you would have to cast it to use String methods.
In plain java i'm use something like
rolesList.toArray(new Integer[rolesList.size()]);
for converting list to array. Don't know in android.
How about this
List a = new ArrayList();
a.add("wer");
a.add("sff");
String[] f= (String[]) a.toArray(new String[0]);
System.out.println(f[0]);