Java - Trouble reading data from a list of 2D arrays - java

I have created a list of 2D arrays containing randomly generated number values for different locations.
public static int Prices[][] = new int[Cities.length][ItemNames.length];
public static List<int[][]> CityPrices = new ArrayList<int[][]>();
public static void NewDay()
{
for(int i = 0; i<Cities.length; ++i)
{
Prices[i] = PriceGenerator.ReturnPricesForCity(i);
//This method returns an array of random integers
}
CityPrices.add(Prices);
}
But then later when I want to retrieve the price history for a specific item for the amount of days passed, it returns the same value for each day
int Prices[] = new int[GlobalVariables.CityPrices.size()];
String sTest = "";
for(int i = 0; i < Prices.length; ++i)
{
Prices[i] = GlobalVariables.CityPrices.get(i)[spinCity.getSelectedItemPosition()][spinItem.getSelectedItemPosition()];
sTest = sTest + Prices[i] + ",";
}
In this case, the values returned by sTest was : 6055,6055,6055,6055,6055, for five consecutive days.
If I would for instance add a day, the values would change to a range of a new number, which in this case was : 7294,7294,7294,7294,7294,7294,
Please show me what I am doing wrong, as I have been trying to figure this one out the past 4 days with no luck.

Every element in your CityPrices list is the same: in each case, you are adding the Prices two-dimensional array. Your loop modifies Prices[i], but it doesn't change Prices, which is still a reference to the same two-dimensional array right the way through.
I think you're imagining it will pass the contents of the array in its current state, but it doesn't: it passes a reference to the array to the .add() method, so any subsequent changes to the array will be reflected in the contents of CityPrices.
If at the end of your loop you try
CityPrices.get(0) == CityPrices.get(1)
you'll see it returns true.

In the assignment: Prices[i] = GlobalVariables.CityPrices.get(i)[spinCity.getSelectedItemPosition()][spinItem.getSelectedItemPosition()]; you are basically referencing an int[][] at the same index for both dimensions.
On top of that, the spinCity.getSelectedItemPosition() invocation might be returning the same index at every iteration of your loop, hence your identical values.
It's hard to assume anything further as you haven't posted the code for spinCity.

Related

Remove duplicates from array by adding non-duplicates to new array

I need to remove duplicate elements from an array by adding elements that are not repeated in the original array to a new array and output the contents of that.
The problem I am having is that when the new array with no duplicates is printed there are zeros being outputted also.
Thus: does Java fill the array with zeros?
public static boolean hasDuplicates(int arrayNum[])
{
boolean dupFound = false;
int ctr1 =0;
while (ctr1<arrayNum.length && !dupFound)
{
int ctr2 = ctr1+1; // be 1 ahead each time ctr1 increments
while(ctr2<arrayNum.length)
{
if(arrayNum[ctr1] == arrayNum[ctr2])
dupFound = true;
ctr2++;
}
ctr1++;
}
return dupFound;
}
public static int[] removeDuplicates(int[] arrayNum)
{
if(hasDuplicates(arrayNum) == false)
return arrayNum;
else
{
int outArray[] = new int[arrayNum.length];
int ctr1=0;
int ctr2 = ctr1+1;
int index = 0;
boolean dupFound = false;
while(ctr1<arrayNum.length)
{
dupFound = false;
ctr2 = ctr1+1;
while(ctr2<arrayNum.length && !dupFound)
{
if(arrayNum[ctr1] == arrayNum[ctr2])
dupFound = true;
ctr2++;
}
if(dupFound == false)
{
outArray[index] = arrayNum[ctr1];
index++;
}
ctr1++;
}
return outArray;
}
}
public static void testRemoveDuplicates()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter size of input array");
int array[] = new int[input.nextInt()];
System.out.println("Enter number of ints required");
for(int i=0; i<array.length; i++)
{
array[i] = input.nextInt();
}
int outArray[] = new int[array.length];
outArray = removeDuplicates(array);
for(int i=0; i<outArray.length; i++)
{
System.out.println(outArray[i]);
}
}
Here:
int outArray[] = new int[array.length];
That code assumes that you have exactly array.length array elements in your output array. And that is of course a too high number! The point is: when you create a new array of that size, the whole array is initially populated with 0 values. And your code will only "overwrite" a few slots of that output array; and all other slots stay at their initial 0 default value.
The point is: you first have to compute how many duplicates you have in your input array; and then you create a new array with exactly that number.
Alternatively, you could be using List<Integer> instead of int[]; as Java collections have the ability to grow dynamically. (or, you can keep increasing that array for collecting duplicates "manually"; that can be done, too - just a bit of complicated code to get there).
And the direct immediate answer is: yes, exactly - Java arrays are "pre-filled"; see here.
You can fix all of your problems (and probably make the code substantially faster in the process since it'll no longer have quadratic complexity) by using standard Java API calls to store the unique elements in a Set, and then turn the values in that set back into an array.
The main caveat is that you'd need to use Integer rather than int:
Set<Integer> s = new LinkedHashSet<Integer>(Arrays.asList(inputArray));
Integer[] outputArray = s.toArray(new Integer[0]);
The LinkedHashSet preserves insertion order, so you'll get the elements back in the same order as they originally appeared albeit without the duplicates.
May be you are wasting too much memory here by considering the worst case scenario where all input given are different while declaring the output array size. More Optimized Approach is that you can have an List<Integer> or ArrayList<Integer> which can store the unique values and then at last , If you want unique values in Array than declare the ArraySize same as the ArrayList<Integer> or List<Integer> size and just in one linear loop , You can copy all the data.
Does Java fill the array with zeros?
Yes , Whenever you declare the integer array , It will be having all its elements as 0. If you want to reset the value of Array to a particular value , You can use this method Arrays.fill(int array[] , int default_value). This can be done in O(list_size) complexity which is linear.
For your purpose more better approach would be use of HashSet<Integer> which holds only unique elements and which is Dynamic in nature so no need to waste extra space as well as it can make your work very easy.
So first you need to all elements in the HashSet<Integer> and then by using Iterator you can easily iterate through it but the insertion order can be disturbed here. So as replied by #Alnitak You can use LinkedHashSet<Integer> to have insertion order same.
A sample code using HashSet :
HashSet<Integer> set=new HashSet<Integer>();
int total_inputs=sc.nextInt();
for(int i=0;i<total_inputs;i++)
set.add(sc.nextInt());
Iterator itr=set.iterator();
while(itr.hasNext())
System.out.println((int)itr.next());
Note : Here input order will not be preserved.
Does Java fill the array with zeros?
Yes, java will initialize every element of your int array to 0. Therefore using arr.length will not work for you as it doesn't return the logical length of your array. You need to track the number of elements of your array yourself. The following line in your code has no meaning
int outArray[] = new int[array.length];
because outArray starts pointing to a different array as returned by your method removeDuplicates.
I need to remove duplicate elements from an array by adding elements
that are not repeated in the original array to a new array
The easiest thing you can do is the following way:
In your method removeDuplicates,
Find the highest number from the given input array, increment it by 1 and assign it to a variable.
int max = Arrays.stream(arrayNum).max().getAsInt() + 1;
Modify your if block from
if(arrayNum[ctr1] == arrayNum[ctr2])
dupFound = true;
to
if(arrayNum[ctr1] == arrayNum[ctr2]) {
dupFound = true;
arrayNum[ctrl] = max;
max++;
}

Define array from another array

I'm trying to define an array starting from data that come from another array.
The code will explain the situation better than thousands words.
public class QualityCheck {
public QualityCheck (JTable table)
{
//the data come from a JTable (that represents a school timetable)
String [] dailyLessons= new String[table.getColumnCount()];
String [] dailyClasses= new String[table.getColumnCount()];
//checking all the days
for (int i=1; i<table.getColumnCount(); i++)
{
//checking all the hours in a day
for (int j=0; j<table.getRowCount(); j++)
{
//lesson is an array that contains the subject and the room in which the subject is erogated
//lesson[0] contains the subject
//lesson[1] contains the room
String[] lesson = ((TabellaOrario.MyTableModel)table.getModel()).getLesson(j,i);
//I'd like to put ALL the daily subjects in dailyLesson
dailyLessons[j] = lesson[0];
//I'd like to put All the daily rooms in dailyClasses
dailyClasses[j] = lesson[1];
}
//trying if dailyLessons has the elements
for (String s: dailyLessons)
{
System.out.println(s);
}
}
}
}
If a run this code, the compiler protest with this error:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 7
and it evidence the string
dailyLessons[j] = lesson[0];
How can I do to define dailyLesson?
You are allocating both of the arrays to the same size table.getColumnCount(),
and then you use index j for both of them again, which goes up to table.getRowCount() - 1.
You probably should allocate one of them to size table.getRowCount(), and then use j as the index for only that one, and i for the other, but you never use dailyClasses so I'm not sure.
Edit:
Apparently the intent is to fill both the arrays with the data of one column. Then the fix is to change the size of the arrays to the amount of rows:
// Changed table.getColumnCount() -> table.getRowCount()
String [] dailyLessons= new String[table.getRowCount()];
String [] dailyClasses= new String[table.getRowCount()];
You init the arrays with table.getColumnCount() and loop using j < table.getRowCount().
If table.getColumnCount() is smaller that table.getRowCount() then you will get AIOBE.
You need at least to init the arrays with table.getRowCount().
EDIT
You could create a little class with encapsulates dailyLessons and dailyClasses
class Lesson {
public String dailyLesson;
public String dailyClass;
}
and create an array of that class, this way you'll always have the same number of daily lessons and classes:
String [] lessons = new Lesson [table.getRowCount()];
and later inside the loop:
lessons.dailyLesson = lesson[0];
lessons.dailyClass = lesson[1];
Also you could use an ArrayList instead of a simple array so you wont have to bother about the size of the array.

List.add() Class Expected

I'm taking a Java class in College. My instructor is actually a teacher for languages derived from C, so she can't figure out what's going on with this piece of code. I read on this page http://docs.oracle.com/javase/6/docs/api/java/util/List.html that I could use the syntax "list[].add(int index, element)" to add specific objects or calculations into specific indexes, which reduced the amount of coding needed. The program I'm looking to create is a random stat generator for D&D, for practice. The method giving the error is below:
//StatGenrator is used with ActionListener
private String StatGenerator ()
{
int finalStat;
String returnStat;
//Creates an empty list.
int[] nums={};
//Adds a random number from 1-6 to each list element.
for (int i; i > 4; i++)
nums[].add(i, dice.random(6)+1); //Marks 'add' with "error: class expected"
//Sorts the list by decending order, then drops the
//lowest number by adding the three highest numbers
//in the list.
Arrays.sort(nums);
finalStat = nums[1] + nums[2] + nums[3];
//Converts the integer into a string to set into a
//texbox.
returnStat = finalStat.toString();
return returnStat;
}
My end goal is to use some kind of sorted list or method of removing the lowest value in a set. The point of this method is to generate 4 random numbers from 1-6, then drop the lowest and add the three highest together. The final number is going to be the text of a textbox, so it is converted to a string and returned. The remainder of the code works correctly, I am only having trouble with this method.
If anyone has any ideas, I'm all ears. I've researched a bit and found something about using ArrayList to make a new List object, but I'm not sure on the syntax for it. As a final note, I tried looking for this syntax in another question, but I couldn't find it anywhere on stackoverflow. Apologies if I missed something, somewhere.
'int nums[]' is not a List, it's an array.
List<Integer> intList = new ArrayList<>();
creates a new ArrayList for example.
You can access Elements in the list directly with the following Syntax :
intList.get(0); // Get the first Element
You can sort Lists with the Collections class :
Collections.sort(intList);
Here are some informations about Collections in Java : http://docs.oracle.com/javase/tutorial/collections/
Arrays are fixed size, so you need to allocate space for all the slots at the start. Then to put numbers into the array assign to nums[i]. No add() method needed.
int[] nums = new int[4];
for (int i = 0; i < 4; i++)
nums[i] = dice.random(6) + 1;
Arrays.sort(nums);
finalStat = nums[1] + nums[2] + nums[3];
Alternatively, if you really want a dynamically-sized array, use an ArrayList. An ArrayList can grow and shrink.
List<Integer> nums = new ArrayList<Integer>();
for (int i = 0; i < 4; i++)
nums.add(dice.random(6) + 1);
Collections.sort(nums);
finalStat = nums.get(1) + nums.get(2) + nums.get(3);
Notice how different the syntax is due to ArrayList being a class rather than a built-in type.
nums[].add(i, dice.random(6)+1); //Marks 'add' with "error: class
expected"
You are trying to use add on an array. List is a dynamic array, but that doesn't mean that array == List. you should use List instead.
List<Integer> nums=new ArrayList<Integer>();
//Adds a random number from 1-6 to each list element.
for (int i; i > 4; i++)
nums.add(i, dice.random(6)+1);
You're mixing arrays and lists.
Have a look at the tutorial:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
http://docs.oracle.com/javase/tutorial/collections/index.html

ArrayList of integer arrays

I'm trying to write a simple game where an enemy chases the player on a grid. I'm using the simple algorithm for pathfinding from the Wikipedia page on pathfinding. This involves creating two lists with each list item containing 3 integers. Here's test code I'm trying out to build and display such a list.
When I run the following code, it prints out the same numbers for each array in the ArrayList. Why does it do this?
public class ListTest {
public static void main(String[] args) {
ArrayList<Integer[]> list = new ArrayList<Integer[]>();
Integer[] point = new Integer[3];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 3; j++) {
point[j] = (int)(Math.random() * 10);
}
//Doesn't this line add filled Integer[] point to the
//end of ArrayList list?
list.add(point);
//Added this line to confirm that Integer[] point is actually
//being filled with 3 random ints.
System.out.println(point[0] + "," + point[1] + "," + point[2]);
}
System.out.println();
//My current understanding is that this section should step through
//ArrayList list and retrieve each Integer[] point added above. It runs, but only
//the values of the last Integer[] point from above are displayed 10 times.
Iterator it = list.iterator();
while (it.hasNext()) {
point = (Integer[])it.next();
for (int i = 0; i < 3; i++) {
System.out.print(point[i] + ",");
}
System.out.println();
}
}
}
First of all, several of the other answers are misleading and/or incorrect. Note that an array is an object. So you can use them as elements in a list, no matter whether the arrays themselves contain primitive types or object references.
Next, declaring a variable as List<int[]> list is preferred over declaring it as ArrayList<int[]>. This allows you to easily change the List to a LinkedList or some other implementation without breaking the rest of your code because it is guaranteed to use only methods available in the List interface. For more information, you should research "programming to the interface."
Now to answer your real question, which was only added as a comment. Let's look at a few lines of your code:
Integer[] point = new Integer[3];
This line creates an array of Integers, obviously.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 3; j++) {
point[j] = (int)(Math.random() * 10);
}
//Doesn't this line add filled Integer[] point to the
//end of ArrayList list?
list.add(point);
//...
}
Here you assign values to the elements of the array and then add a reference to the array to your List. Each time the loop iterates, you assign new values to the same array and add another reference to the same array to the List. This means that the List has 10 references to the same array which has been repeatedly written over.
Iterator it = list.iterator();
while (it.hasNext()) {
point = (Integer[])it.next();
for (int i = 0; i < 3; i++) {
System.out.print(point[i] + ",");
}
System.out.println();
}
}
Now this loop prints out the same array 10 times. The values in the array are the last ones set at the end of the previous loop.
To fix the problem, you simply need to be sure to create 10 different arrays.
One last issue: If you declare it as Iterator<Integer[]> it (or Iterator<int[]> it), you do not need to cast the return value of it.next(). In fact this is preferred because it is type-safe.
Finally, I want to ask what the ints in each array represent? You might want to revisit your program design and create a class that holds these three ints, either as an array or as three member variables.
I would highly recommend to enclose the integer array of 3 numbers into a meaningful class, that would hold, display and control an array of 3 integers.
Then in your main, you can have an growing ArrayList of objects of that class.
You have an extra ) here:
element = (int[])it.next()); //with the extra parenthesis the code will not compile
should be:
element = (int[])it.next();
Besides the problem in the other answer, you cal it.next() two times, that cause the iterator move forward two times, obviously that's not what you want. The code like this:
element = (int[])it.next());
String el = (String)element;
But actually, I don't see you used el. Although it's legal, it seems meaningless.

Java Array Creation and Array Name Change

Can you create a line of code, within a while-loop, that will create a new array AND change the array's name with each iteration of the while loop?
Example:
int size = 10;
int name_count = 1;
while(size <= 100)
{
//name_count is changing the name of the array by calling it
// "array1", "array2", etc...
//I know this may not be correct code for changing the name of
// the array, but it is suppose to get the point across.
int[] array(name_count) = new int[size];
for (int i = 0; i <= size; i++)
{ /* Adding numbers to an array */ }
size = size + 5;
name_count++;
}
Identifier names need to be defined at compile time. So you can't explicitly use a different variable name on each iteration of the loop.
Another problem with your pseudo-code is that, if the array were to be declared inside the loop, it would fall out of scope when the loop completes, so there wouldn't be much point.
To do something like this you need to use some collection to hold the arrays, and it would be easier to make them explicit objects instead of just arrays. Something like:
List<List<Integer>> listOfArrays = new ArrayList<List<Integer>>();
while (size <= 100) {
List<Integer> listOfNumbers = new ArrayList<Integer>(size);
/* insert loop here to add numbers to listOfNumber */
size += 5;
name_count += 1;
}
Then you can access each list of numbers using an index into listOfArrays -- equivalent to naming each one with the index, but handled at runtime instead of compile time.
You cannot change the array's name, It will just re-declare the array with each successful loop. (It will be a new blank array.) I think what you are looking for is a two dimensional array.
int[][] myArray = new int[3][3];

Categories