Writing to arrays in Java - java

I have an array of integers and I want to save pairs of integers using the index of the array as one of the indexes and the value as the other integer.
For example, if I wanted to save the pair: 2, 4. I could do: dependencias[2] = 4 (or dependencias[4] = 2.
It should be fairly simple, right? But I can't do it! I keep getting an out of bounds error. This is my code:
int recursoA, recursoB;
dependencias = new int[numberDependencias];
/* I tried setting them all to 0, to see if that was the problem.
* It didn't do anything, as I expected. */
for (int i = 0; i < numberDependencias; i++){
dependencias[i] = 0;
}
int recursoA, recursoB,cont = 0;
while (numberDependencias > 0){
System.out.println("Introduce el primer recurso");
recursoA = Integer.parseInt(br.readLine());
if ((recursoA > 1) && (recursoA <= recursos)){
System.out.println("Introduce el segundo recurso");
recursoB = Integer.parseInt(br.readLine());
dependencias[recursoA] = recursoB; // This is the problem, apparently.
numberDependencias--;
}
Sorry the variables are in Spanish, but hopefully you'll see what I'm talking about. I can't translate it right now.

The integer you're reading-in (recursoA) has to be greater than 1 and less than "recursos". The problem, is that "recursos" is probably greater than "numberDependencias"...which is the max size of your array.
Either alter this line to make sure that recursoA is always less then numberDependencias.
if ((recursoA > 1) && (recursoA < numberDependencias)){
Or, define your array size to be "recursos".
dependencias = new int[recursos];

A Java array has fixed bounds. If you declare it like this:
a = new int[3];
then you can only assign values to a[0], a[1] and a[2]. What you want here is not an array but a Map.
Map<Integer, Integer> dependencias = new HashMap<Integer, Integer>();
dependencias.put(4000, 2000);
dependencias.get(4000) // returns 2000

I suspect the error is being caused by the line:
if ((recursoA > 1) && (recursoA <= recursos)){
What value is recursos being set to? If it is above numberDependencias then an out of bounds error would make sense. Additionally, the open brace at the end of that line doesn't seem to be being closed. This will certainly cause an error!

What values are you trying to introduce for recursoA?
I think you should check if this value is between 0 and numberDependencias-1. Keep in mind that arrays begin at 0, so if you create an array with 4 positions, you can assign values to array[0] ... array[3].

Well I believe what you're saying that you are creating an array that's the size of the number of these "pairs" you have. However, this will give you out of range errors if you have a number larger then the number of pairs, you will get errors. If this is unclear, say you have 2 pairs, (9, 3) and (3, 4), and you try to save them in your array as dependencias[3] = 9 and dependencias[4] = 3. Your going to get errors as dependencias is not large enough for those values to be used as indexes.
To fix this use a Map, which is made like this,
Map<Integer, Integer> dependencias = new HashMap<Integer, Integer>();
then you can add things to your map, like so:
dependencias.put(someInteger1, someInteger2);
Finally you can call back that pair using:
dependencias.get(someInteger1); //this will return someInteger2

Your problem is right here numberDependencias > 0, because you initialze an array with number of elements starting at 0. When you start to fill at numberDependencias, you're try to put in an element out of the arrays size. Try numberDependencias-1 > 0 and use array[numberDependencias] instead of recursoA, excepting you want to initialize your array with recursoA.
Instead of an array I would prefer java.util.HashMap where you can easily put key-value pairs into, besides that you don't need to worry about initializing your size or out of bounds errors.

Related

Java arrays objects and initializer confusion

I'm learning java and was told arrays are implemented as objects. But they show two different codes without diving into details.
First they ask us to use arrays like this, but the downside is to manually add the values:
int nums[] = new int[10];
nums[0] = 99;
nums[1] = -622;
.
.
.
Then they use this in some programs saying new is not needed because Java automatically does stuff:
int nums[] = {99, - 10, 100123, 18, - 972 ......}
If the second code is shorter and allows me to use arrays straightaway whats the point of the first code if they do the same thing but the first one require more code to input value by hand.
Let's say you were initializing an array of 1 million values, would you use the second method? No, because you would have a huge java file.
The first method is essentially allocating space:
int[] array = new int[1000000];
Creates 1 million spaces in memory with default value 0. Now if you want to initialize them, you may use a loop:
for (int i = 0; i < array.length; i++) {
array[i] = i;
}
If you wanted an array of 10 million values, you only change one number:
// Just add a 0 to 1000000
int[] array = new int[10000000]
Now, if the size of your array changes, you don't have to change the loop. But if you used the second method and wanted an array of 10 million values, you would have to add 9 million values, and 9 million commas to your java file - not scalable.
int[] array = {1, 2, 3, 4, ... 1000000};
The second method is not "scalable." It only works for small arrays where you can confidently assume that the default values of that array won't change. Otherwise, it makes A LOT more sense to use the first (more common) method.
//This is one way of declaring and initializing an array with a pre-defined size first
int nums[] = new int[10];
//This is initializing the array with a value at index 0
nums[0] = 99;
//This is initializing the array with a value at index 1 and likewise allocating rest of array index values
nums[1] = -622;
//This is another way of declaring and initializing an array directly with pre-defined values. Here if you see instead of declaring array size first, directly the values are initialized for it
int nums[] = {99, - 10, 100123, 18, - 972 ......}
It depends on the way you prefer to use the arrays, but you must remember that whenever you use "new" keyword, there is a new space or resource created every time in memory.
When you don't know the items of array at the time of array declaration, then prefer method-1,
and,
when you know the all the values of array at the time of array declaration, then go for method-2
Imagine you want to generate a series of random integers at runtime and want to store in the array:
int[] array = new int[1000000];
Random r = new Random();
for (int i = 0; i < array.length; i++)
array[i] = r.nextInt();

Pseudo code: Random Permutation

I have a pseudo code that I have translated into java code but anytime I run the code, I get an empty arraylist as a result but it is supposed to give me a random list of integers.
Here is the pseudo code:
Algorithm 1. RandPerm(N)
Input: Number of cities N
1) Let P = list of length N, (|P|=N) where pi=i
2) Let T = an empty list
3) While |P| > 0
4) Let i = UI(1,|P|)
5) Add pi to the end of T
6) Delete the ith element (pi) from P
7) End While
Output: Random tour T
Here is the java code:
public static ArrayList<Integer> RandPerm(int n)
{
ArrayList<Integer> P = new ArrayList<>(n);
ArrayList<Integer> T = new ArrayList<>();
int i;
while(P.size() > 0)
{
i = CS2004.UI(1, P.size());// generate random numbers between 1 and the size of P
T.add(P.get(i));
P.remove(P.get(i));
}
return T;
}
I don't know what I am doing wrong.
ArrayList<Integer> p = new ArrayList<>(n);
... creates an empty list with an initial capacity of n.
All this does is tell the ArrayList what size array to initialise as backing store - most of the time you achieve nothing useful by specifying this.
So your while(p.size() > 0) runs zero times, because p.size() is zero at the start.
In the pseudocode "where pi=i" suggests to me that you want to initialise the list like this:
for(int i=0;i<n;i++) {
p.add(i)
}
(I have lowercased your variable name - in Java the convention is for variables to startWithALowerCaseLetter -- only class names StartWithUpperCase. It's also the Java convention to give variables descriptive names, so cityIdentifiers perhaps)
You may want to know that, even if you fix the problem that P is always empty, there are 2 more issues with your implementation.
One is that P.remove(P.get(i)) does not necessarily remove the ith item if the list has equal value items. It scans from the beginning and removes the first occurrence of the item. See ArrayList.remove(Object obj). You should use P.remove(i) instead for the correct results.
Then the performance is O(n^2). The reason is that ArrayList remove an item by shifting all the subsequent items one slot to the left, which is an O(n) operation. To get a much better performance, you can implement your own "remove" operation by swapping the item to the end. When you generate the next random index, generate it within the range [0, beginning index of the removed items at the end). Swapping is O(1) and the overall performance is O(n). This is called Knuth Shuffle by the way.

Array List Index 0 size 0 error

I'm making a program of the Card game War and I need the cards to not reappear so I used an Array list. I'm having trouble with this array list as it's supposed to be random and remove the number, but I get the error IndexOutOfBoundsException: Index 0, Size 0
List<Integer> values = new ArrayList<Integer>();
Random random = new Random();
Integer rand = random.nextInt(values.size()+1);
Integer cardId = values.get(rand);
values.remove(rand);
First add your Card(s) to your values List (e.g. probably not Integer).
What I'm saying is this, you need a deck of cards before you can play.
Your list is empty and you're
1) Trying to retrieve a value
2) Trying to remove a value
Which throws an error because the list is empty.
Sidenote: you can define rand and cardId as int, instead of Integer. Autoboxing/unboxing will take care of that for you.
Add values to your list and it will work as expected (and if you change random.nextInt(values.size()+1) to random.nextInt(values.size())).
You get this error because you try to access index 0 of an empty array, as it says. You cannot do this.
Your code has multiple issues.
You are not actually storing anything in values.
The acceptable range of indexes for .get() is 0 to size-1. The return range of random.nextInt(size+1) is 0 to size. This can produce out of range index values. Array indexes start at 0.
Provide the code for the values in the array...Or add values in the array.
You need to first give the List values before you can get values
List<Integer> values = new ArrayList<Integer>();
Random random = new Random();
Integer rand = random.nextInt(values.size()+1);
Try this to put values
for (int i = 1; i <= 52; i++){
values.add(i);
}
Integer rand = random.nextInt(values.size() + 1);

Confusing regarding .get and .set in an ArrayList

(I'm new at Java, coming over from Python ---)
I'm going through a tutorial and they've created a program which counts how many times a number appears in a file, then returns that number. One particular part of the program is somewhat mysterious to me and deals with the ArrayList's .get and .set (methods? functions?). The program goes like this:
// (Scan a file with the numbers, say, 2 2 3 4, and put it into data1 variable.)
// (Make An Empty ArrayList with a bunch of 0's)
Scanner data1 = null;
ArrayList<Integer> count = new ArrayList<Integer>();
Integer idx;
while(data1.hasNextInt()){
idx = data1.nextInt();
System.out.println(idx);
System.out.println(count.get(idx)+1);
count.set(idx,count.get(idx)+1);
}
//Then prints out all the values; the ArrayList contains the number of times the number n occurs in the n-th index.
My question comes at the "while" part. For concrete, let's assume data1 has the numbers 2 2 3 4. It seems that it takes idx = 2, then puts a 1 in count[2], which is reasonable. It then takes idx = 2 again (the next integer in data1) and puts a 2 in count[2], which is also reasonable. At this point, the next number in data1 makes idx = 3, but it occurs at the index 2 in the ArrayList, so it should put a 3 in count[3], which is incorrect.
So, what is .get and .set doing here? Do they pop the elements off of the list when they're done with it? Am I overlooking something?
A .get() will not automagically get elements from a List which does not have that many elements. Note: list indices, like arrays, start at 0.
If you do:
final List<Integer> = new ArrayList<Integer>();
list.get(0);
this is a runtime error (IndexOutOfBoundsException) because your list has no elements.
You have to fill it:
list.add(1); // append an element
list.get(0); // returns element at index 0
list.get(1); // IndexOutOfBoundsException!
The .set() method takes an index and a value at an argument. In a similar vein, you cannot set an element which does not already exist, except at the very end of the list:
// start from an empty list
list.set(1, 32); // IndexOutOfBoundsException!
list.set(0, 32); // OK
Final note: try not to use list[i], bracket indices are used for arrays ;) Note that arrays are not resizabe in Java. Lists (which are an implementation of a Collection), however, are. But you must append to them.
So, what this line does:
count.set(idx, count.get(idx) + 1);
is take the value at index idx, add 1 to it, and sets back this value at the same index.
In your specific case, what you are looking for is a sparse array. In Java we use a HashMap<Integer, Integer> for that purpose. You don't need any initialization with zeros, but you do need to check for null:
final Integer curr = count.get(idx);
count.put(idx, curr == null? 1 : curr+1);
You are currently using an ArrayList, which acts like an array, but makes it easier to expand it - for example, add elements to it.
What you want is the java equivalent of the python dict, a key/value storage, in java, this is called a HashMap<K,V> (docs).
Scanner data1 = null;
HashMap<Integer, Integer> count = new HashMap<Integer, Integer>();
Integer idx;
while(data1.hasNextInt()) {
idx = data1.nextInt();
System.out.println(idx);
Integer g = count.get(idx)+1;
if(g == null) {
g = 0;
}
g++;
System.out.println(g);
count.put(idx, g);
}

Hard java array situation

I am trying to compute this problem all day long and it seems i can't figure out how to do it:
List<ArrayList<Word>> words = new ArrayList<ArrayList<Word>>();
words index 0 has : defin 3,countri 1,chairman 2,year 1,
words index 1 has : defin 2,build 1,countri 1,round 3
words index 2 has : cup 3,patent 1,round 2,year 2,
What I want to do is to find which words belong to other arrays and add their numbers together and then divide that with first occurrence.
For example:
When index = 0 and word = defin --> 3/2+0
When index = 0 and word = countri --> 1/1+0
....
When index = 1 and word = defin --> 2/3+0
When index = 1 and word = round --> 3/2+0
....
When index = 2 and word = cup --> 3/0+0 but must do 3/1 so it wont "break".
I'm tempted to suggest Guava's Multiset, which is typically used to track multiple occurrences of the same objects -- like a Map<E, Integer>, but with much less hassle.
List<Multiset<String>> words;
int index;
Map<String, Double> ratios = Maps.newHashMap();
for(Multiset.Entry<String> entry : words.get(index).entrySet()) {
String word = entry.getElement();
int wordCountIn0 = words.get(0).count(word);
if (wordCountIn0 == 0) wordCountIn0 = 1;
ratios.put(word, (double) entry.getCount() / wordCountIn0);
}
I'm not 100% clear on your problem, but as best as I understand it, this should work.
Encapsulate your data inside a class that maintains all pertinent data in various data stores.
Then query via that object. Think of it as a databse - you have the core data, but you also have things like indexes and views that present that data in a given way according to your usage requirements.
I figured out how to do it, not the best way in terms of efficiency but it works. In any way it is not efficiency that am after but rather to make it 'just work'.
So what i do is that i loop over the size of the first array and check whether the word belongs to any of the arrays or not. When i find that i store its frequency value. Then i go over the arrays again except for that that i have found the word the first place. I sum up all the frequencies and in the end i dived the first frequency but the summed up from the others.

Categories