Can array's index be negative number in Java? - java

public static void main(String[] args) {
int[] a = new int[10];
a[1] =2;
a[-1] = -2;
a[0] = 0;
System.out.println(a[-1]);
}
I write codes above, editor didn't judge it illegal, but when I run it, it give me
"Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1"
So is negative number index in java is illegal all the time? Or there's some special situation can let array's index be negative number?

Let's have a look at Oracle's documentation here. This is what it says:
An array object contains a number of variables. The number of variables may be zero, in which case the array is said to be empty. The variables contained in an array have no names; instead they are referenced by array access expressions that use non-negative integer index values. These variables are called the components of the array. If an array has n components, we say n is the length of the array; the components of the array are referenced using integer indices from 0 to n - 1, inclusive.
Also,
All array accesses are checked at run time; an attempt to use an index
that is less than zero or greater than or equal to the length of the
array causes an ArrayIndexOutOfBoundsException to be thrown.
To answer the question, no, index can't be negative.

There is no support in java for negative indices.
Last element can be accessed using
array[array.length-1] = lastElement;

In short, no, they cannot be negative.
From the docs(using get for example)
ArrayIndexOutOfBoundsException - If the specified index argument is negative, or if it is greater than or equal to the length of the specified array

So is negative number index in java is illegal all the time?
Yes.
Or there's some special situation can let array's index be a negative number?
You could write own array-like collection type where negative indices would be valid. It would be rather a domain-specific type because I can't think of any general applications.
A simple example would be
// define an anonymous class that overrides ArrayList's get behaviour
List<String> list = new ArrayList<String>() {
#Override
public String get(int index) {
return super.get(Math.abs(index));
}
};
list.add("a");
list.add("b");
System.out.println(list.get(-1)); // b
System.out.println(list.get(1)); // b
It's not what I would recommend you do. It's confusing and unusual for any Java developer.

Short answer: No.
Slightly less short answer: Array indices range from 0 to the length of the array minus 1.
E.g. :
int[] ints = new int[5];
ints[0] = 1; // fine
ints[4] = 1; // fine
ints[-1] = 1; // ArrayIndexOutOfBoundsException thrown
ints[5] = 1; // ArrayIndexOutOfBoundsException thrown

In java, Negative index can't be used. It is 0 based positive index. If used negative index then java will throw "ArrayIndexOutOfBoundsException" Exception.

arrays in java can not be indexed using negative numbers, the "problem" is that there is no such unsigned integers defined until now in java, so writing myArr[x] will compile as soon a x is a valid numerical index

As #Darshan Mehta's answer says, negative numbers are not allowed as array indexes. However, you can always write your own array class that allows negative indices.
Here's my example using generics.
public class ModuloArray<E> {
int size;
E[] array;
public ModuloArray(int size) {
if (size <= 0)
throw new RuntimeException("not positive");
this.size = size;
array = (E[]) new Object[size];
}
public ModuloArray(E... elements) {
if (elements == null)
throw new RuntimeException("null");
this.size = elements.length;
array = elements;
}
public E get(int index) {
return array[Math.floorMod(index, size)];
}
public void set(int index, E element) {
array[Math.floorMod(index, size)] = element;
}
}
public class Main {
public static void main(String[] args) {
System.out.println("*** ModuloArray with first constructor ***");
ModuloArray<String> myArray = new ModuloArray<>(3);
myArray.set(-1, "apple");
myArray.set(-2, "orange");
myArray.set(-3, "banana");
System.out.println(myArray.get(-3));
System.out.println(myArray.get(-2));
System.out.println(myArray.get(-1));
System.out.println(myArray.get(0));
System.out.println(myArray.get(1));
System.out.println(myArray.get(2));
System.out.println();
System.out.println("*** ModuloArray with second constructor ***");
ModuloArray<String> myArray2 = new ModuloArray<>("glazed donut", "chicken burger", "apple soda");
System.out.println(myArray2.get(-2));
System.out.println(myArray2.get(3));
}
}
The above example outputs:
*** ModuloArray with first constructor ***
banana
orange
apple
banana
orange
apple
*** ModuloArray with second constructor ***
chicken burger
glazed donut
Array indexes in Java are valid only if 0 <= index < array.length is true. However, because ModuloArray uses Math.floorMod(int x, int y) to access the array elements, any integer (including negative numbers) can be used as a valid index. This behavior is similar to how indexing works for lists in Python.

Related

Out of Bound Error at arraylist in prefix average algorithm

java.lang.IndexOutOfBoundsException: error occurs when adding a single value to the first arrayList, in order to perform prefix averages as such that the value of A is computed by
id like to note that using arrays in this algorithm worked but when trying to switch to an arraylist does the issue occur.
Array A Contents of A[i]
A[0] (X[0])/1
A[1] (X[0]+X[1])/2
A[2] (X[0]+X[1]+X[2])/3
A[3] (X[0]+X[1]+X[2]+X[3])/4
A[4] (X[0]+X[1]+X[2]+X[3]+X[4])/5
A[5] (X[0]+X[1]+X[2]+X[3]+X[4]+X[5])/6
A[6] (X[0]+X[1]+X[2]+X[3]+X[4]+X[5]+X[6])/7
A[7] (X[0]+X[1]+X[2]+X[3]+X[4]+X[5]+X[6]+X[7])/8
A[8] (X[0]+X[1]+X[2]+X[3]+X[4]+X[5]+X[6]+X[7]+X[8])/9
A[9] (X[0]+X[1]+X[2]+X[3]+X[4]+X[5]+X[6]+X[7]+X[8]+X[9])/10
started off with a.get(i) = s/(i+1); that didn't help. then tried setting the contents of a[i] with the out come of s/(i+1) still no avail
public class prefixAverage{
public static void main(String args[]) {
ArrayList <Float> X = new ArrayList <Float>();
X.add(9f);
System.out.print(PrefixAverage(X));
}
public static ArrayList<Float> PrefixAverage(ArrayList<Float> X){
ArrayList <Float> a = new ArrayList <Float>();
float s = 0;
for (int i = 0; i<= X.size()-1;i++) {
s = s +X.get(i);
a.set(i,s/(i+1));
System.out.print(a.get(i)+", ");
}
return a;
}
}
I am expecting an increasing size average as the index of A increase
List::set sets an existing element to a new value. In your case, a is an empty list so you can't use that method (or you get an exception).
You probably meant to use a.add(i, value) instead, which will insert an element at the given index (and expand the list by one item).
In your case, you are inserting at index 0, then 1 etc., so you can simply use a.add(value).

What do array[] and array[i] operators do in Java?

I'm trying to teach myself coding, and I stumbled on an example I don't understand. Could someone give me an overview of what this code is supposed to do? I'm a bit confused about int a[] and what is later int a[i]. I know what an array is, but could someone please explain how this is being used in this context? Thank you in advance.
public class all {
public int select(int a[],int n,int x)
{
int i=0;
while(i<n && a[i]<x)
{
if(a[i]<0)
a[i]=-a[i];
i++;
}
return(a[i-1]);
}
}
This
if(a[i]<0)
a[i]=-a[i];
i++;
is he same like this
if(a[i]<0) {
a[i]=-a[i];
}
i++;
a[i] -> value at the position i, into the Array
if(a[i]<0) { -> if the value at position i is smaller than 0, also negative number
a[i]=-a[i]; -> replace the value with a reverse sign.
i++ -> increment loop Counter
Also what is done here: negative numbers convert to positive numbers.
while(i<n && a[i]<x) -> i = loop counter; if i smaller n and the value at position i in the array is smaller than x, then go into the loop.
return(a[i-1]); -> return the last value, that has been checked into the while loop
the method gets an array and two int args n and x (as a side note, I must say the names leave a lot to be desired...)
anyway, lets see what are the args for. they both are used in the while loop. the condition i<n tells us that n serves as upper limit to the iteration, while the condition a[i]<x tells us that x is used as upper limit to the values in the array.
so far, we can say:
select method receives an array, int arg specifying iteration-upper-limit and int arg specifying cell-value-upper-limit.
iterate over the array until you reach position specified by iteration-upper-limit or you reach a cell value that exceeds cell-value-upper-limit (which ever comes first)
can you continue to say what's being done inside the loop? it's fairly straightforward.
1.) a[] is the declaration of array.size is not defined.
2.)In a[i], i is the index number of the array...that means indicating the position of the element in array.
a[] is an array and we do not know its length. n must be lower than the length of a[] or it will throw an exception. It it traverses from the first element toward the last untill it one element is larger than x. it returns these element's absolute value which were traversed

Java Code More Efficient

I am creating a code here but I believe there is a way making the following more efficient. I tried many ways but it does not seem to work.
protected void randomise() {
int[] copy = new int[array().length]; //This makes the new int called randomIndex
// used to indicate if elements have been used
boolean[] used = new boolean[array().length]; //calling "used" as a new boolean for the array
Arrays.fill(used,false);
/**
* if index = 0, it means their is nothing in the index.
* if you apply a random number, it will copy that number to an array called index.
* if randomIndex in use, then the boolean becomes true.
*/
for (int index = 0; index < array().length;) {
do {
randomIndex = randomIndex();
} while (used[randomIndex]); //when random is in use, do the follow instruction.
copy[index] = array[index]; //copy the value value to an array called index.
used[randomIndex] = true; //when randomIndex is in use, then it becomes true.
}
//Of course, if there an extra random stores in the array, the index list is increased by one (index++).
for (int index =0;index < array().length; index++) {
array()[index] = copy[index]; //This tells where to copy the index value. in this case, it is a index array.
}
Do you have to use randomIndex?
If not you can use your bool[] to eliminate that do {} while() by sequentially adding the value to copy (which isn't a great name) and choosing a randInt in the range of the len of elements that haven't been selected, then using that bool[] to count a walk through the array elements ( to make your choice for the next element in copy.
You seem to want to randomly re-order an array. If so, then indeed there is a much more efficient solution. You are currently keeping two extra arrays on the size of the input (O(n)) while you do not have to.
The random shuffling is a common problem, and obviously there have been proposed several algorithms to accomplish this task. One of the most efficient algorithms is Knuth's algorithm for random permutation
The algorithms idea is, loop over the array once, and for each number i, perform a random exchange between i and a (random) array index between 0 and i. This guarantees that the array with be shuffled (meaning that each item will have equal possibility to be placed in each of the array indexes), in O(n) time and without using any extra space.
In short,
for (int i = 0; i < index; i++) {
int r = random.nextInt(i + 1);
exchange(array, i, r);
}
It is simple - use some collection of indexes and remove element when you used it. This way should looks like:
List<Integer> indexes = new ArrayList<>(array.length);
for (int i = 0 ; i < array.length ; i++) {
indexes.add(i);
}
Random r = new Random();
while (indexes.size() > 0) {
int randomIndex = r.nextInt(indexes.size());
int index = indexes.remove(randomIndex);
copy[index] = array[index];
}
Please note that:
you should check what is exact collection will be more efficient in your situation
Another way - create list values for array and use Collections.shuffle method on this list.
Additional another way - use some recursive algorithm to do that work.

Why am I getting ArrayIndexOutOfBoundsException?

So I got this assignment while my teacher is away, and basically I have to make a student project. The student has a name, marks, and average. To calculate the average I decided to store the marks inside a int[] array.
public void addQuiz(int m)
{
int l = (marks.length);
marks[l] = m;
}
int[] marks = new int[8];
But when I run the function:
student.addQuiz(90);
I get:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8
Any help?
I'm not sure what the int[8] part does but it was in the tutorial I followed and it would give me a null pointer without it. There are eight marks in total so I just made it 8.
You can't dynamically add things to an array. You should use an array list instead.
Arraylist<Integer> marks = new ArrayList<Integer>();
then in your addQuiz method:
public void addQuiz(int m) {
marks.add(m)
}
You'll probably also need to change your method for calculating the average a bit, but that should be trivial and I'll leave it to you.
The error says: ArrayIndexOutOfBoundsException: 8
You have an array with 8 elements, indexed from 0 to 7 (inclusive). This array has a length of 8, and you are actually trying to access marks[8], when you only can go up to 7.
In Java, Array index starts from '0'. so, you cannot access the index of the array equal to the length of the array.if your arrays length is '8', then the last index of the array is '7' not '8'. if you are trying to access the illegal index of the array, then ArrayIndexOutOfBoundException is thrown. the code should be changed to
public void addQuiz(int m)
{
int l = (marks.length); //assuming marks is an array of length '8'
marks[l-1] = m; //index is 7 now
}
To calculate the average, you need to sum up the contents of the array (provided all the values are of int values) and then divided by the lenght of the array
int sum = 0;
int avg = 0;
for(int i=0; i<array.length;i++){
sum =sum+array[i];
}
avg = sum/array.length;
Hope this gives an idea
Use Arraylist<Integer> and then you can add to the list dynamically
There is not index in this array for this marks[l] = m;. use marks[l-1] = m;
You can call this for loop in main for getting marks 8 times.
for(int i=0;i<8;i++)
student.addQuiz(<marks you want to enter>, i);
You can define addQuiz function like below
public void addQuiz(int m, int arrayIndex)
{
marks[arrayIndex] = m;
}
int[] marks = new int[8]; //this will be as it is
These are minimal changes. You can make your code better by passing array marks to addQuiz as a parameter. But this will also work, its just that this is not the best way to write code.

Sorting matched arrays in Java

Let's say that I have two arrays (in Java),
int[] numbers; and int[] colors;
Each ith element of numbers corresponds to its ith element in colors.
Ex, numbers = {4,2,1}
colors = {0x11, 0x24, 0x01}; Means that number 4 is color 0x11, number 2 is 0x24, etc.
I want to sort the numbers array, but then still have it so each element matches up with its pair in colors.
Ex. numbers = {1,2,4};
colors = {0x01,0x24,0x11};
What's the cleanest, simplest way to do this? The arrays have a few thousand items, so being in place would be best, but not required. Would it make sense to do an Arrays.sort() and a custom comparator? Using library functions as much as possible is preferable.
Note: I know the "best" solution is to make a class for the two elements and use a custom comparator. This question is meant to ask people for the quickest way to code this. Imagine being at a programming competition, you wouldn't want to be making all these extra classes, anonymous classes for the comparator, etc. Better yet, forget Java; how would you code it in C?
You could use sort() with a custom comparator if you kept a third array with the index, and sorted on that, leaving the data intact.
Java code example:
Integer[] idx = new Integer[numbers.length];
for( int i = 0 ; i < idx.length; i++ ) idx[i] = i;
Arrays.sort(idx, new Comparator<Integer>() {
public int compare(Integer i1, Integer i2) {
return Double.compare(numbers[i1], numbers[i2]);
}
});
// numbers[idx[i]] is the sorted number at index i
// colors[idx[i]] is the sorted color at index i
Note that you have to use Integer instead of int or you can't use a custom comparator.
It seems like the cleanest thing to do would be to create a custom property class that implements Comparable. For example:
class Color implements Comparable {
private int number;
private int color;
// (snip ctor, setters, etc.)
public int getNumber() {
return number;
}
public int getColor() {
return color;
}
public int compareTo(Color other) {
if (this.getNumber() == other.getNumber) {
return 0;
} else if (this.getNumber() > other.getNumber) {
return 1;
} else {
return -1;
}
}
}
Then you can separate your sorting algorithm from the ordering logic (you could use Collections.sort if you use a List instead of an array), and most importantly, you won't have to worry about somehow getting two arrays out of sync.
If you'd be willing to allocate some extra space, you could generate another array, call it extra, with elements like this:
extra = [0,1,...,numbers.length-1]
Then you could sort this extra array using Arrays.sort() with custom comparator (that, while comparing elements i and j really compares numbers[extra[i]] and numbers[extra[j]]). This way after sorting the extra array, extra[0] would contain the index of the smallest number and, as numbers and colours didn't move, the corresponding colour.
This isn't very nice, but it gets the job done, and I can't really think of an easier way to do it.
As a side note, in the competition I usually find the C++ templated pairs and nice maps indispensable ;)
Why not introduce an object to represent a number and a color and implement a comparator function for that?
Also, do you really need an array, why not use something derived from Collection?
I like #tovare's solution. Make a pointer array:
int ptr[] = { 1, 2, 3 };
and then when you sort on numbers, swap the values in ptr instead of in numbers. Then access through the ptr array, like
for (int i = 0; i < ptr.length; i++)
{
printf("%d %d\n", numbers[ptr[i]], colors[ptr[i]]);
}
Update: ok, it appears others have beaten me to this. No XP for me.
An example illustrating using a third index array. Not sure if this is the best implementation.
import java.util.*;
public class Sort {
private static void printTable(String caption, Integer[] numbers,
Integer[] colors, Integer[] sortOrder){
System.out.println(caption+
"\nNo Num Color"+
"\n----------------");
for(int i=0;i<sortOrder.length;i++){
System.out.printf("%x %d %d\n",
i,numbers[sortOrder[i]],colors[sortOrder[i]]);
}
}
public static void main(String[] args) {
final Integer[] numbers = {1,4,3,4,2,6};
final Integer[] colors = {0x50,0x34,0x00,0xfe,0xff,0xff};
Integer[] sortOrder = new Integer[numbers.length];
// Create index array.
for(int i=0; i<sortOrder.length; i++){
sortOrder[i] = i;
}
printTable("\nNot sorted",numbers, colors, sortOrder);
Arrays.sort(sortOrder,new Comparator<Integer>() {
public int compare(Integer a, Integer b){
return numbers[b]-numbers[a];
}});
printTable("\nSorted by numbers",numbers, colors, sortOrder);
Arrays.sort(sortOrder,new Comparator<Integer>() {
public int compare(Integer a, Integer b){
return colors[b]-colors[a];
}});
printTable("\nSorted by colors",numbers, colors, sortOrder);
}
}
The output should look like this:
Not sorted
No Num Color
----------------
0 1 80
1 4 52
2 3 0
3 4 254
4 2 255
5 6 255
Sorted by numbers
No Num Color
----------------
0 6 255
1 4 52
2 4 254
3 3 0
4 2 255
5 1 80
Sorted by colors
No Num Color
----------------
0 6 255
1 2 255
2 4 254
3 1 80
4 4 52
5 3 0
One quick hack would be to combine the two arrays with bit shifts. Make an array of longs such that the most significant 32 bits is the number and the least significant 32 is the color. Use a sorting method and then unpack.
Would it suffice to code your own sort method? A simple bubblesort would probably be quick to code (and get right). No need for extra classes or comparators.
Credit to #tovare for the original best answer.
My answer below removes the (now) unnecessary autoboxing via Maven dependency {net.mintern : primitive : 1.2.2} from this answer: https://stackoverflow.com/a/27095994/257299
int[] idx = new int[numbers.length];
for( int i = 0 ; i < idx.length; i++ ) idx[i] = i;
final boolean isStableSort = false;
Primitive.sort(idx,
(i1, i2) -> Double.compare(numbers[i1], numbers[i2]),
isStableSort);
// numbers[idx[i]] is the sorted number at index i
// colors[idx[i]] is the sorted color at index i
I guess you want performance optimization while trying to avoid using array of objects (which can cause a painful GC event).
Unfortunately there's no general solution, thought.
But, for your specific case, in which numbers are different from each others, there might be two arrays to be created only.
/**
* work only for array of different numbers
*/
private void sortPairArray(int[] numbers, int[] colors) {
int[] tmpNumbers = Arrays.copyOf(numbers, numbers.length);
int[] tmpColors = Arrays.copyOf(colors, colors.length);
Arrays.sort(numbers);
for (int i = 0; i < tmpNumbers.length; i++) {
int number = tmpNumbers[i];
int index = Arrays.binarySearch(numbers, number); // surely this will be found
colors[index] = tmpColors[i];
}
}
Two sorted arrays can be replace by Int2IntOpenHashMap, which performs faster run, but memory usage could be double.
You need to sort the colors array by its relative item in the numbers array. Specify a comparator that compares numbers and use that as the comparison for the colors array.
The simplest way to do this in C, would be bubblesort + dual pointers. Ofcourse the fastest would be quicksort + two pointers. Ofcourse the 2nd pointer maintains the correlation between the two arrays.
I would rather define values that are stored in two arrays as a struct, and use the struct in a single array. Then use quicksort on it. you can write a generic version of sort, by calling a compare function, which can then be written for each struct, but then you already know that :)
Use a TreeMap

Categories