Java ArrayList contents not propagating - java

My code runs an algorithm on an array, and stores the results in an ArrayList. The problem is that I am not able to access the contents of the ArrayList for subsequent processing. Though my actual code is thousands of lines long, I have trapped the problem, and have re-created the problem in the short code segments below. You can take the three classes below and run them in your IDE without changes to reproduce the problem yourself. As you can see, it populates the ArrayList within makeArrayList.java, but yet the contents of the ArrayList are not subsequently visible in getArrayList.java.
Can anyone show me how to fix the code below so that the contents of the ArrayList become visible/usable in getArrayList.java and in myGUI.java?
Here is the code for the three classes:
The code for myGUI.java is:
package arrayListPractice;
import java.awt.Dimension;
import javax.swing.JFrame;
public class myGUI extends JFrame {
public myGUI() {
super("test GUI");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(300, 200));
getArrayList getArrList = new getArrayList();
getArrList.getPeaks();
this.pack();}
public static void main(String args[]) {
myGUI myFrame = new myGUI();
myFrame.setVisible(true);}}
The code for getArrayList.java is:
package arrayListPractice;
import java.util.*;
public class getArrayList {
public static ArrayList<Integer> PeakList;
int myLength = 3500;
double[] myArray=new double[myLength];
public ArrayList<Integer> getPeaks(){
for(int h=0;h<myLength;h++){myArray[h]=Math.sqrt((double)h);}
PeakList = new makeArrayList(myArray,myLength);
System.out.println("in getArrayList.getPeaks, PeakList.size() is: "+PeakList.size());
return PeakList;}}
The code for makeArrayList.java is:
package arrayListPractice;
import java.util.*;
public class makeArrayList extends ArrayList<Integer> {
ArrayList<Integer> myArrayList= new ArrayList<Integer>();
public makeArrayList(double[] myArray, int arrayLength) {
// NOTE: My actual code does many transformations to myArray. The resulting myArrayList
// contains only 1/1000 of the points in myArray. This code is just simplified for debugging.
for(int i=0;i<arrayLength;i++){myArrayList.add((int)Math.pow(myArray[i],2));}
System.out.println("in makeArrayList, PeakList.size() is: "+myArrayList.size());}}

You are confusing and combining inheritance and composition in the same class:
class makeArrayList extends ArrayList<Integer> {
ArrayList<Integer> myArrayList = new ArrayList<Integer>();
public makeArrayList(double[] myArray, int arrayLength) {
// NOTE: My actual code does many transformations to myArray. The
// resulting myArrayList
// contains only 1/1000 of the points in myArray. This code is just
// simplified for debugging.
for (int i = 0; i < arrayLength; i++) {
myArrayList.add((int) Math.pow(myArray[i], 2));
}
System.out.println("in makeArrayList, PeakList.size() is: "
+ myArrayList.size());
}
}
Note that this class both contains an ArrayList and extends ArrayList and you're trying to make both ArrayLists interchangeable , but they're not.
Some Suggestions:
There's no need for this class to extend ArrayList, so get rid of the extends and instead simplify and clarify tings by just using composition.
Avoid using static anything unless you have a very good reason for doing so. This is not part of your main problem, but is a problem with your sample code.
For the sake of others reading your code and either helping you or grading you, don't be afraid to use whitespace to make your code more readable. Page real estate is not that expensive. Also read up on and use Java naming conventions including capitalizing the first letter of class names. This will make it much easier for others (us!) to read and understand your code.
e.g.,
import java.util.ArrayList;
public class MyNonGUI2 {
public static void main(String args[]) {
GetArrayList2 getArrList = new GetArrayList2();
getArrList.getPeaks();
}
}
class GetArrayList2 {
public ArrayList<Integer> PeakList;
int myLength = 3500;
double[] myArray = new double[myLength];
public ArrayList<Integer> getPeaks() {
for (int h = 0; h < myLength; h++) {
myArray[h] = Math.sqrt((double) h);
}
PeakList = new MakeArrayList2(myArray, myLength).getArrayList();
System.out.println("in GetArrayList2.getPeaks, PeakList.size() is: "
+ PeakList.size());
return PeakList;
}
}
class MakeArrayList2 {
ArrayList<Integer> myArrayList = new ArrayList<Integer>();
public MakeArrayList2(double[] myArray, int arrayLength) {
for (int i = 0; i < arrayLength; i++) {
myArrayList.add((int) Math.pow(myArray[i], 2));
}
System.out.println("in MakeArrayList2, PeakList.size() is: "
+ myArrayList.size());
}
public int size() {
return myArrayList.size();
}
public ArrayList<Integer> getArrayList() {
return new ArrayList<Integer>(myArrayList);
}
}

Related

How do I use on method to get the sizes of two different-sized arrayslists?

I'm new to Java and I want to use one method, getCount, to get the sizes of two arraylists that are not the same size. What code could I use so that I can call, for example, examp1.getCount and examp2.getCount, and get the two different sizes?
This is frankly as basic a question as it gets, and google could have helped you with this easily. Here's your entire method if you want to design your own.
public static int getCount(ArrayList A){
return A.size();
}
In your method, use .size() to get the sizes of the two ArrayLists
and store the sizes in the array and then return that array.
Suppose you create 2 lists li1 and li2 then :
package output;
import java.util.ArrayList;
import java.util.List;
public class CalculateLength {
public static void main(String[] args) {
List<Integer> li1= new ArrayList<>();
li1.add(1);
li1.add(2);
getCount(li1);
List<Integer> li2= new ArrayList<>();
li2.add(1);
li2.add(2);
li2.add(3);
li2.add(4);
getCount(li2);
}
public static int getCount(List list) {
System.out.println("LEngth = " + list.size());
return list.size();
}
}

How to create a class with a list of elements from another class without breaking the dependency injection rule?

I have class that has several fields.
public class Foo {
int firstCoef;
int secondCoef;
public Foo(String args){
this.firstCoef=Integer.parseInt(args[0]);
this.secondCoef=Integer.parseInt(args[1]);
}
}
The arguments are assigned this way because I create several members of this class by reading data from .csv.
I have another class that manages a list of Foo instances. It creates the whole list at once by reading it from file and uses the list for calculation. When creating a list in class constructor, it uses new Foo(string).
public class FooManager {
protected List<Foo> allFoos = new ArrayList<Foo>();
public FooManager(List<String[]> input) {
String[] line;
for (int lineNumber = 0; lineNumber < input.size(); lineNumber++) {
line = input.get(lineNumber);
allFoos.add(new Foo(line));
}
}
public int calculate(int number) {
int result = 0;
for (Foo foo : allFoos) {
result += Math.pow(number + foo.getFirstCoef(), foo.getSecondCoef());
}
return result;
}
}
From what I understand, this is considered bad design because the dependencies can't be injected. Also, it is hard to test. How could I change the design without complicating the input? The only goal of both classes is to be able to perform the calculation in the end.
You could add another layer, by adding a class that does the translation from the List to List:
public class FooParser implements Function<String[], Foo> {
public Foo apply(String[] input)
for (int lineNumber = 0; lineNumber < input.size(); lineNumber++) {
String[] line = input.get(lineNumber);
allFoos.add(new Foo(line));
}
}
}
And then use it in the constructor of FooManger:
public FooManager(FooParser parser, List<String[]> input) {
allFoos = parser.apply(input);
}
This way you have another part of logic in separate class - and it is easier to test in isolation.

Updating a variable & adding numbers to two different lists

I have just started doing threading this week and I'm kind of stuck on one of the exercises.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
public class RandomNumberConsumer implements Runnable {
ArrayBlockingQueue<Integer> numbersProduced;
public RandomNumberConsumer(ArrayBlockingQueue<Integer> numbersProduced) {
this.numbersProduced = numbersProduced;
}
//Should eventually hold the sum of all random number consumed
int sumTotal = 0;
List<Integer> below50 = new ArrayList();
List<Integer> aboveOr50 = new ArrayList();
#Override
public void run() {
//In this exercise, we start four threads, each producing 100 numbers, so we know how much to consume
for (int i = 0; i < 400; i++) {
try {
System.out.println("first" + numbersProduced.take());
System.out.println("second" + numbersProduced.take());
System.out.println("third" + numbersProduced.take());
System.out.println("fourth" + numbersProduced.take());
} catch (InterruptedException ex) {
Logger.getLogger(RandomNumberConsumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public int getSumTotal() {
return sumTotal;
}
public List<Integer> getBelow50() {
return below50;
}
public List<Integer> getAboveOr50() {
return aboveOr50;
}
}
Basically what I don't understand is how to update sumTotal variable to show all consumed random numbers since they're stored in ArrayBlockingQueue<> and also how to insert them into either the below 50 or above Or 50 Lists.
What about don't use numbersProduced.take() in the run method and define a new function, even in RandomNumberConsumer class?
int foo() throws InterruptedException{ //because of take function
int a=numbersProduced.take();
if(a<50)
below50.add(a);
else
over50.add(a);
sumTotal=sumtTotal+a;
return a;
}
now in run call foo and not numbersProduced.take()
I must tell you, i hope you know it: if you use threads which modify the same variable you must use Semaphore or synchronized methods.
Ps: sorry for bad English :)

When I create a 2D array outside of my constructor, I'm not able to resize it, but when I create one inside of it, I'm not able to access it

I'm trying to create a method which will create an object which contains a 2D boolean array, with int parameters as the number of rows and columns. Then inside the class, I have methods that try to grab the length and width of that array. The two ways I tried to solve this problem were:
public GameOfLife(int rows, int cols) {
boolean[][] society = new boolean[rows][cols];
}
public int numberOfRows() {
return society.length;
}
In my tests, this attempt was giving me the error that society cannot be resolved to a variable. Then I tried:
private boolean[][] society;
public GameOfLife(int rows, int cols) {
boolean[][] temp = new boolean[rows][cols];
society = temp;
}
EDIT: Oops, forgot to add my method for numberOfColumns:
public int numberOfColumns() {
return cols;
}
But the issue with this one was that it was returning 0 instead of 4 when I tried:
#Test
public void FailedTestingRowsAndCols(){
GameOfLife g1 = new GameOfLife(4,4);
assertEquals(4, g1.numberOfColumns());
}
I'm rather new to this, so I apologize if this is a dumb question, but I'm not really sure about all the details of where and when variables expire, which is giving me a lot of difficulties. THank you for any help!
When I create a 2D array outside of my constructor, I'm not able to resize it, but when I create one inside of it, I'm not able to access it
Take note that you will never be able to resize an array. An array once created has its size fixed. You are merely assigning your current array to reference to another newly created array (which gives you the illusion that you successfully resized it).
As for your question of not being able to access it is highly likely the variable you created exist within different scope.
You can use the following codes (which is very similar to yours), it works fine for me. Hence I am guessing your error does not actually comes from the code snippet you showed.
class TestRunner
{
public static void main(String[] args){
GameOfLife gol = new GameOfLife(5, 3);
System.out.println(gol.getColumns());
System.out.println(gol.getRows());
}
}
class GameOfLife
{
private boolean[][] society;
public GameOfLife(int rows, int cols){
society = new boolean[rows][cols];
}
public int getColumns(){
return society[0].length;
}
public int getRows(){
return society.length;
}
}
Output:
5
3
I don't see any problems with what you have posted so far. The below example works fine for me:
public class GameOfLife {
public static void main(String[] args) {
GameOfLife g1 = new GameOfLife(4,4);
System.out.println(g1);
}
private boolean[][] society;
#Override
public String toString() {
final StringBuffer sb = new StringBuffer("GameOfLife{");
sb.append("society=").append(society == null ? "null" : Arrays.deepToString(society));
sb.append('}');
return sb.toString();
}
public GameOfLife(int rows, int cols) {
boolean[][] temp = new boolean[rows][cols];
society = temp;
}
}

Get and set methods not changing the array

I have extended a class in hope to store a global array (make the array within the class be seen by another object) by using the set1sub(sub.local) method
public class BattleShipsClient extends ShipLocations implements Runnable, BattleShipConstants
{
BattleShipsClient()
{
}
public void placeBoard(int player) throws IOException// this is only called once and not updated when clicked again
{
while(getLocations())
{
while(isWaiting())//true
{
toServer.writeInt(player);
int row = getRowSelected();
int col = getColumnSelected();
int choice=Integer.parseInt(JOptionPane.showInputDialog("Please 1 for a sub, 2 for a battleship and 3 for a destroyer"));
clickCount ++;
if(clickCount >2)
{
setLocation(false);
continueToPlay=true;
}
if (choice ==1 &&sub.placed==false)
{
String orientation =JOptionPane.showInputDialog("please enter your orientations");
if(orientation.equalsIgnoreCase("h"))
{
//row os the same
//column number will be sent, then plus one on the other side
sub.local = new int[2][2];
sub.local[0][0] =row;
sub.local[0][1]=col;
sub.local[1][0]=row;
sub.local[1][1] =col+1;
toServer.writeInt(row);
toServer.writeInt(col);
toServer.writeChar('s');
sub.placed=true;
setp1sub(sub.local);
/*setp1sub(new int[][]{{row,col},
{row,col+1}});*/
grid[row][col+1].setToken(getMyToken());
}
I then have a ship Locations class however when i create a new object of the ship locations class and try to read this array it always is set to [[0, 0], [0, 0]], ive tried making it static and atomic
public class ShipLocations {
int [][] p1sub;
public ShipLocations()
{
p1sub = new int[2][2];
}
public int[][] getp1sub()
{
return p1sub;
}
public void setp1sub(int[][] local) {
for (int i = 0;i <local.length;i++)
{
for(int j = 0;j<local.length;j++)
{
p1sub [i][j]= local[i][j];
}
}
}
}
Whenever you create a new instance of ShipLocations(or a subclass) the constructor is called, which in your case, reinitializes the p1sub array.
In your design, you are overusing inheritance. You should not inherit from a class just to use its methods and variables.
To store a global variable in a class:
public class ShipLocations {
static int [][] p1sub;
static{
p1sub = new int[2][2];
}
public static void setp1sub(...){...}
public static int[][] getp1sub(){...}
}
And then use it by class name instead of creating instances:
int [][] x = ShipLocations.getp1sub();
Though the use of global variables shoud be avoided when possible. It is considered bad design and might be a problem when reusing the code.
The correct way of doing this is to have the ShipLocations object as a local variable in BattleShipsClient and set it when initializing new instance. You will then first create a common ShipLocation object and hand it to every client that should see the same array.

Categories