ArrayList is being cleared and overwritten in Java - java

I'm having some trouble in Java.
I have two classes, suprad and coupling.
Couplings are formed by an ArrayList of suprad's (the list is called supradscoupled), and two values(integer num and double q)
Every coupling instantiated is written in an ArrayList called Createdcouplings.
During the main program, I have to declare two couplings between two suprad's each (total of 4 suprad's at all). There is no issue when I declare the first coupling (formed by the two firsts suprad's).
But when I declare the second one trough adding the other two suprad's at the ToBeCoupledSupRads ArrayList, the older couplings are being cleared and then overwritten by the new coupling.
At the end, I get two couplings repeated formed only by the new one.
The MainWindow class:
public class MainWindow {
(...)
public static List<suprad> ToBeCoupledSupRads = new ArrayList<suprad>();
public static void main(){
(...)
int i = ToBeCoupledComboBox.getSelectedIndex();
suprad stemp = suprad.Createdsuprads.get(i);
(...)
// adding new suprad to this ArrayList makes the ArrayList Createdcouplings have its registered data overwritten!
ToBeCoupledSupRads.add(stemp);
(...)
}
}
The coupling class:
public class coupling {
public int num;
public static int total = 0;
public double q;
public static List<coupling> Createdcouplings = new ArrayList<coupling>();
public List<suprad> supradscoupled = new ArrayList<suprad>();
public coupling(List<suprad> nums, double q)
{
(...)
this.supradscoupled = aux;
total++;
this.num = total;
this.q=q;
// this is the ArrayList that is having its older data cleared and overwritten unwantedly
Createdcouplings.add(this);
}
}
I would appreciate some help, the Java project is being compiled with JavaSDK 1.8.0_221 with IntelliJ IDEA Community.

Related

Array of structures in a structure in JNA

My native code is
typedef struct driver_config {
unsigned int dllVersion;
unsigned int channelCount;
unsigned int reserved[10];
ChannelConfig channel[64];
} DriverConfig;
In Java my class looks like this
public class DriverConfig extends Structure {
public int dllVersion;
public int channelCount;
public int[] reserved= new int[10];
ChannelConfig[] channel = new ChannelConfig[64];
public DriverConfig() {
super();
init();
}
private void init() {
for (int i = 0; i < channel.length; i++) {
channel[i]= new ChannelConfig();
}
}
#Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "dllVersion", "channelCount", "reserved" });
}
//toString()...
}
The method declaration is
int getDriverConfig(DriverConfig driverConfig);
I tried to access the method like this
DriverConfig driverConfig = new DriverConfig();
status = dll.INSTANCE.getDriverConfig(driverConfig);
System.out.println("DriverConfig Status: " + status);
System.out.println(driverConfig.toString());
If channel.length is replaced with less then 50 the array is initialized correctly but with channel.length it did not work. It even did not show any error just nothing.
Your getFieldOrder() array does not include the last element (channel) of your structure. I see in your comments that you attempted to do this but received an error because you have not declared it public. All elements of your structure must be listed in the FieldOrder and also declared public so they can be found with reflection.
Also, with JNA 5.x (which you should be using) the #FieldOrder annotation is preferred.
You haven't identified the mapping for ChannelConfig, but your question title and this API link matching your structure indicate that it is a nested structure array. Structure arrays must be allocated using contiguous memory, either by directly allocating the native memory (new Memory()) which requires knowing the structure size, or by using Structure.toArray(). Allocating in a loop as you have done will end up with memory for each new structure allocated at possibly/probably non-contiguous locations in native memory. Given that you state that it appears to work for some values, you might be getting lucky with contiguous allocations, but your behavior is certainly undefined.
Your structure mapping should therefore be:
#FieldOrder ({"dllVersion", "channelCount", "reserved", "channel"})
public class DriverConfig extends Structure {
public int dllVersion;
public int channelCount;
public int[] reserved= new int[10];
public ChannelConfig[] channel = (ChannelConfig[]) new ChannelConfig().toArray(64);
}

Creating an object of one class in another class?

I have two classses and I wonder why I always get an error when I try to create an object of class "Knoten" in a method of class "Graph".
Class Graph
public class Graph
{
static Knoten[] knotenliste;
public void punktHinzufuegen(int x, int y){
for(int i=0;i<Gui.zaehler;i++){
knotenliste[i]=new Knoten(x,y);
}
}
}
Class Knoten:
public class Knoten{
int xPos;
int yPos;
public Knoten(int x,int y){
xPos=x;
yPos=y;
}
}
Every time I call method punktHinzufuegen I get an error. Thanks for helping..
Your problem is a very easy problem to solve, so I'll give a short explanation/solution.
What your current problem is, is that you are not defining your knotenliste.
You should define it as the following field:
private static Knoten[] knotenliste = new Knoten[Gui.zaehler];
I would suggest that you do not use a static value but start working with either a fixed ArrayList (in order to index your graph points) or a Queue. Both of those can be found on the Java documentation if you're intested in reading about them.
What I would have done is the following:
public class Graph {
private final ArrayList<Knoten> knotenliste = new ArrayList<>(Gui.zaehler);
public void punktHinzufuegen(int x, int y) {
for (int i = 0; i < Gui.zaehler; i++) {
// Keep in mind that the List#add(int index, E element) will
// shift all the elements previously in the array to the right.
knotenliste.add(i, new Knoten(x, y));
}
}
}
With this you do not only stop abusing the static keyword, but you also have a more flexible Collection to save your Knoten in.
You haven't initialized your array and I think you are getting NullPointerException while adding elements. You need to initialize it before adding elements to it
static Knoten[] knotenliste = new Knoten[<SOME_INT_VALUE>];

Using Runnable to run a method by multiple threads

In my program, I want to create multiple threads in one of the methods where each thread has to run a specific method with a given input. Using Runnable, I have written this snippet.
class myClass {
public myClass() { }
public void doProcess() {
List< String >[] ls;
ls = new List[2]; // two lists in one array
ls[0].add("1"); ls[0].add("2"); ls[0].add("3");
ls[1].add("4"); ls[1].add("5"); ls[1].add("6");
// create two threads
Runnable[] t = new Runnable[2];
for (int i = 0; i < 2; i++) {
t[ i ] = new Runnable() {
public void run() {
pleasePrint( ls[i] );
}
};
new Thread( t[i] ).start();
}
}
void pleasePrint( List< String > ss )
{
for (int i = 0; i < ss.size(); i++) {
System.out.print(ss.get(i)); // print the elements of one list
}
}
}
public class Threadtest {
public static void main(String[] args) {
myClass mc = new myClass();
mc.doProcess();
}
}
Please note, my big code looks like this. I mean in one method, doProcess(), I create an array of lists and put items in it. Then I want to create threads and pass each list to a method. It is possible to define the array and lists as private class members. But, I want to do that in this way.
Everything seems to be normal, however, I get this error at calling pleasePrint():
error: local variables referenced from an inner class must be final or effectively final
pleasePrint( ls[i] );
How can I fix that?
The reason you are getting this error is straightforward and clearly mentioned - local variables referenced from an inner class must be final or effectively final. This is, in turn, because, the language specification says so.
Quoting Guy Steele here:
Actually, the prototype implementation did allow non-final variables
to be referenced from within inner classes. There was an outcry from
users, complaining that they did not want this! The reason was interesting: in order to support such variables, it was necessary to
heap-allocate them, and (at that time, at least) the average Java
programmer was still pretty skittish about heap allocation and garbage
collection and all that. They disapproved of the language performing
heap allocation "under the table" when there was no occurrence of the
"new" keyword in sight.
As far as your implementation goes, instead of using an array of list, I'd rather use a list of lists.
private final List<List<String>> mainList = new ArrayList<>();
You can create new lists and insert them into the main list in the constructor depending on the number of lists you want.
public ListOfLists(int noOfLists) {
this.noOfLists = noOfLists;
for (int i = 0; i < noOfLists; i++) {
mainList.add(new ArrayList<>());
}
}
You can then change your doProcess() method as follows:
public void doProcess() {
for (int i = 0; i < noOfLists; i++) {
final int index = i;
// Using Lambda Expression as it is much cleaner
new Thread(() -> {
System.out.println(Thread.currentThread().getName());
pleasePrint(mainList.get(index)); // Pass each list for printing
}).start();
}
}
Note: I used an instance variable named noOfLists to (as the name suggests) store the number of lists I need. Something as follows:
private final int noOfLists;
To populate the list, you could do:
mainList.get(0).add("1");
mainList.get(0).add("2");
mainList.get(0).add("3");
mainList.get(1).add("4");
mainList.get(1).add("5");
mainList.get(1).add("6");
// And so on...
And you'll get the output something as:
Thread-0
1
2
3
Thread-1
4
5
6
Hope this helps :)
First to that, you will get a NullPointerException here:
ls[0].add("1"); ls[0].add("2"); ls[0].add("3");
ls[1].add("4"); ls[1].add("5"); ls[1].add("6");
Before, yo must instantiate the lists:
ls[0] = new ArrayList<>();
ls[1] = new ArrayList<>();
About the compiler error, try to define the array as final. Change:
List< String >[] ls;
ls = new List[2]; // two lists in one array
By:
final List< String >[] ls = new List[2]; // two lists in one array
This is because you can't access to non-final (or effectively final) variables from a local class.
'ls' is effectively final but probably, since you have defined it in two lines, the compiler is not able to notice that.

Java - Inheritance regarding constructors

So, I'm trying to practice my java skills by applying it to some math homework and making a frequency distribution chart using inheritance. In my head, I envision it as a frequency distribution (parent class = FreqDist) that can have multiple "MyStatClasses" (in the form of the MyStatClass array). Each FreqDist has variables that span across all MyStatClasses which is why I put them in the parent class. However, when I call the MyStatClass constructor, my program gets a StackOverflowError. I think this is because the super(s, i) line calls back to the FreqDist constructor and starts over, causing an infinite loop. Assuming this is the case, how would I fix this?
Ideally, I'd like to access my MyStatClass array and grab values that only apply to that MyStatClass, but I cannot get it to work.
public class FreqDist {
private MyStatClass[] freqClasses;
private double[] dblValuesArray;
private int intNumberOfClasses;
private double dblMax;
private double dblMin;
private int intClassWidth;
public FreqDist(String strValues, int intNumOfClasses) {
System.out.println("This is the beginning of the FreqDist constructor...");
dblValuesArray = getDoubleValues(strValues);
intNumberOfClasses = intNumOfClasses;
dblMin = dblValuesArray[0];
dblMax = dblValuesArray[dblValuesArray.length - 1];
intClassWidth = (int)Math.ceil((dblMax - dblMin) / intNumberOfClasses);
freqClasses = new MyStatClass[intNumberOfClasses];
for (int x = 0; x < freqClasses.length; x++) {
freqClasses[x] = new MyStatClass(strValues, intNumOfClasses);
}
}
public double[] getDoubleValues(String strValues) {
String[] strValuesArray = strValues.trim().split(" ");
dblValuesArray = new double[strValuesArray.length];
for (int x = 0; x < strValuesArray.length; x++) {
dblValuesArray[x] = Double.parseDouble(strValuesArray[x]);
}
Arrays.sort(dblValuesArray);
return dblValuesArray;
}
public int getNumberOfClasses() {
return intNumberOfClasses;
}
public double getMin() {
return dblMin;
}
public double getMax() {
return dblMax;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("What are the values? ");
String values = scan.nextLine();
System.out.print("How many classes? ");
int classes = scan.nextInt();
FreqDist fd = new FreqDist(values, classes);
}
}
public class MyStatClass extends FreqDist {
public MyStatClass(String s, int i) {
super(s, i);
}
}
Ok so this is mostly an issue with a flaw in your design.
From what I understand FreqDist is a class that should contain an array of MyStatClass. You want them to have the same properties so you make MyStatClass extend FreqDist. However when you call FreqDist it MyStatClass which Calls a new MyStatClass over and over and over.
One way to solve this is to create a new class that has the shared properties you want FreqDist and MyStatClass to have, and have those two classes inherit from said class. Then create separate constructors for FreqDist and MyStatClass.
A parent type should never refer to its own subtypes, as yours does. Her the parent initializes subtype instances, which require that each initialize the parent type, which initializes subtype instances, which initialize their parent type, which initializes... KABLOOEY!

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;
}
}

Categories