How to remove a specific child node from a Group in OSGVP? - java

I have the following problem and I don't know how to resolve it.
I have a Group class where I have some Nodes and I add more nodes constantly. One of them is named "figure" and I would like to identify this node to remove it.
For example I have an initial Group:
1 line
2 point
3 figure
And then I add more nodes:
1 line
2 point
3 figure
4 line
5 point
I have used this but I have not got it because I can only use it in one situation:
pp.setNodeName("figure");
int numNodes= this._featureNodes.getNumChildren();
if (this._featureNodes.getChild(numNodes-1).getNodeName() == "figure")
{
this._featureNodes.removeChild(numNodes-1);
}

Use equals() for comapring Strings not == operator. equals() compares whether the nodeName has the same String characters. == compares whether two references reference the same object. Therefore, your if block would be as follows:
if (this._featureNodes.getChild(numNodes-1).getNodeName().equals("figure"))
{
this._featureNodes.removeChild(numNodes-1);
}

I get it!!
The solution was to create a "for" loop to read all items of my group and identify the node "figure" like this:
for (int i = 0 ; i< this._featureNodes.getNumChildren(); ++i){
if (_featureNodes.getChild(i).getNodeName().equals("figure"))
{
this._featureNodes.removeChild(i);
}
}

Related

Can`t compare ArrayList values in Java

Im doing a Java course and in one exercise I have to create three ArrayLists, ask the user to fill the first two with Integers, and then compare both ArrayLists.
The values that donĀ“t repeat are added to the third ArrayList. I already declared the ArrayLists, used Scanner to allow the user to fill the ArrayLists, and that part works.
The problem comes when I try to compare both ArrayLists. I get all sort of alerts in this line ("the if statement is redundant", "Integer values compared using == or !=","Flip operands of the binary operator", "Invert if").
I suspect that what I wrote after the if statement is not very clean, and that I could get some comments about that (Im not an expert in Java), but I do not understand the alerts that the IDE displays. The code compiles and runs just fine until it hits the nested loops. Please help! Thanks.
//Checking for values that dont repeat
for(int i=0;i<listVector1.size();i++){
for(int j=0;j<listVector2.size();i++){
if(listVector1.get(i)==listVector2.get(j)){//Im getting an alert here
repeats=true; //this boolean was previously declared
} else {
repeats=false;
}
if(repeats==false){
int newValue=listVector1.get(i);
listVector3.add(newValue);
}
}
}
First of all, you have a mistake in the second for loop. I expect you want increment j.
Second is comparing you must explicit cast your values from the array or use function equals.
Third your if statement must be out of your second loop. Because I expect you want to add number in third array only one time as it you find.
for(int i = 0; i < listVector1.size(); i++) {
for(int j = 0; j < listVector2.size(); j++) {
if (listVector1.get(i).equals(listVector2.get(j))) {
repeats = true;
break;
} else {
repeats = false;
}
}
if(!repeats){
int newValue=listVector1.get(i);
listVector3.add(newValue);
}
}
This is the real problem here.
Integer values compared using == or !=
The == operator compares the two object's reference. But what you actually want to do is compare the values stored in the reference.
So, you need to use the equals operator.
Or you could explicitly cast one of the values to int and use == on the values like
if(listVector1.get(i) == ((int)listVector2.get(j))){
repeats=true;
} else {
repeats=false;
}
For more reading, you'd google difference between == and equals operator.

Array inside an array: iteration doesn't recognize strings inside of it [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 3 years ago.
I have trouble reading the elements inside a 2d array.
To contextualize, the user delivers an input like this:
7
1
2
3 1 2
4 3
5 4
6 3
7 5 6
Where the first digit is the number of next inputs (n in my code). And every next first digit is a course, and the digits that follow it are it's requirements (courses too). For example, course 3 needs courses 1 and 2 approved.
I need to count the occurrence of a String inside a 2D array but not considering the first element of each array (list1[i][0]). Also the first row list1[0] is not filled to make index call easier (that's why my function starts with i=1).
The problem is that it won't recognize the items that are inside the 2d array, so the count returns always 0. This is my function
static int count(String[][] list, String s, int n) { //n is the number of rows
int x=0;
for (int i=1;i<=n;i++) {
for (int j=1;j<list[i].length;j++) {
if (list[i][j]==s) {
x++;
}
}
}
return x;
}
The function actually works for an array defined like this:
String[][] list1= {{null},{"1"},{"2"},{"3","1","2"},{"4","3"},{"5","4"},{"6","3"},{"7","5","6"}};
Where, for example, count(list1,"1",7) returns 1 and count(list1, "3",7) returns 2.
But for the array where the inputs are saved as strings (list2), supposedly just like list1, the count returns 0.
The way I initialized the 2D array list2:
String[][] list2 = new String[n+1][];
String[] L1 = new String[n+1]; //just an auxiliary array
for (int j=1; j<=n; j++) {
list2[j] = new String[n+1];
L1[j] = sc.nextLine();
list2[j] = L1[j].split(" ");
}
The weird thing is that if a call an array or an element of list2, it returns what is supposed to (for example, using the input above, list2[3]=["3","1","2"]) but the function just doesn't work.
I had the same problem with another homework, and it was related to adding arrays to another array, I couldn't solve it so I changed the way the inputs were saved, but now due to restrictions I have no other choice.
Any help will be appreciated
At Java == means exact same object for object comparison. For String object there is method equals, overrides the Object class equals() method implementation.
equals method returns true if object is a String, not null and represents the same sequence of characters.
static int count(String[][] list, String s, int n) { //n is the number of rows
int x=0;
for (int i=1;i<=n;i++) {
for (int j=1;j<list[i].length;j++) {
if (list[i][j].equals(s)) {
x++;
}
}
}
return x;
}
If equality is not case sensitive use if (list[i][j].equalsIgnoreCase(s))
2 problems:
1: arrays are 0-indexed. Start your loops at 0, not 1
2: use .equals() to compare strings. Never use == for objects unless you know exactly what you're doing
Try using .equals() to compare the value in the matrix to the string s instead of the == operator

Java Implementing Comparable

I am trying to overwrite the compareTo in Java such that it works as follows. There will be two string arrays containing k strings each. The compareTo method will go through the words in order, comparing the kth element of each array. The arrays will then be sorted thusly. The code I have currently is as follows, but it does not work properly.
I need a return statement outside the for-loop. I'm not sure what this return statement should return, since one of the for-loop return statements will always be reached.
Also, am I using continue correctly here?
public int compareTo(WordNgram wg) {
for (int k = 0; k < (this.myWords).length; k++) {
String temp1 = (this.myWords)[k];
String temp2 = (wg.myWords)[k];
int last = temp1.compareTo(temp2);
if (last == 0) {
continue;
} else {
return last;
}
}
}
You want to compare the two string at the same location:
int last = temp1.compare(temp2);
Java compiler mandates all the end points must have a return statement. In your case you must return 0 at end so when both arrays contain completely equal strings the caller will know they are equal.
You should start listening to your compiler, because after looking at your code for 1 minute, I spotted two undefined states: this.myWords.length is 0 and the two words are equal.
Also, I personally find it very difficult to handle multiple method exit points with all possibilities for input considered and rather insert a single returning statement which makes debugging easier and the results more predictable. In your case for example, I would collect the results of compareTo in a collection if they differ from 0 so that after the for-loop has finished, you could decide at the state of this collection if 0 (empty collection) or the first value in the collection could be returned. I like this more formal approach, because it enforces you to think set-like as in "Give me all comparing results where compareTo results in anything else but 0. If this list is empty, the comparing result is 0, otherwise it is the first element of the list."

Strange outOfBoundsException when iterating through lists

I'm writing a program that applies many principles of computational linguistics. My problem at this moment is the following piece of code form a method that "flexibilizes two definitions".
This is, it compares two different definitions of the same word, and in each definition empty or blank spaces will be added to later on work with the altered definitions (with blank spaces added).
Say we have the following two definitions, defining the term "free fall".
1) Free fall descent of a body subjected only to the action of gravity.
2) Free fall movement of a body in a gravitational field under the influence of gravity
There is a list of words called stoplist, which contains the words: "of", "a", "in", "to", and "under". After the process, each word in the definition that is also contained in the stoplist must correspond to a blank space OR another stoplist word of the other definition.
So after executing such process, the previous definitions, represented in two different lists, should look like this:
1) Free fall descent of a body ____ ____ subjected only to the action of gravity.
2) Free fall movement of a body in a gravitational field under the influence of gravity.
The code I wrote to achieve this is the following:
[...]
String[] sList = STOPLIST.split(" "); //this is the stoplist
String[] definition1 = defA1.split(" "); //this is the array of words of the first definition
String[] definition2 = defA2.split(" "); //this is the array of words of the second definition
List<String> def1 = new ArrayList<String>();
List<String> def2 = new ArrayList<String>();
List<String> stopList = new ArrayList<String>();
for(String word : definition1){
def1.add(word); //I transform arrays into lists this way because I used to think that using .asList() was the problem.
}
for(String word : definition2){
def2.add(word);
}
for(String word : sList){
stopList.add(word);
}
int mdef = (def1.size() <= def2.size()) ? def1.size() : def2.size(); //here mdef will have the value of the lenght of the shortest definition, and we are going to use the value of mdef to iterate later on.
for(int i = 0; i < mdef; i++){
if (stopList.contains(def1.get(i))) { //here I check if the first word of the first definition is also found in the stoplist.
if (!stopList.contains(def2.get(i))) { //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
if(mdef == def2.size())
mdef++; //In case the shortest definition is the definition to which we just added spaces, we increment mdef++, because that space added increases the length of the shortest definition, and to iterate in this recenlty extended definiton, we have to increment the index with which we iterate.
}
} else if (stopList.contains(def2.get(i))) { //this else if does the same than the previous one, but checks for the second definition instead of the first one. And adds blanks to def1 instead of def2 if necessary.
if (!stopList.contains(def1.get(i))) {
def1.add(i , " ");
if(mdef == def1.size())
mdef++;
}
}
}
[...]
Now, if you analyze the code carefully, you will realize that not all words of the lengthiest list will be checked, given that we iterate ove the definitions using the lenght of the shortest definition as index. This is fine, the remainding words of the lenghtiest definitions don't have to be checked, they will correspond to null spaces of the other definition (in case the lists don't end up being of the same lenght after the addition of spaces, as the previous exaple shows).
Now, after the explanation, the problem is the following: after running the main class, which calls the method that contains the previous code, a runtime exceptions pops out:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:571)
at java.util.ArrayList.get(ArrayList.java:349)
at main2.main(main2.java:75)
I don't understand why it is finding any of the lists as "empty".
I have tried to solve it in too many ways, I hope a I gave a good explanation.
It may help as a clue that if I assign mdef to the lengthiest size instead of the shortest, that is :
int mdef = (def1.size() >= def2.size()) ? def1.size() : def2.size();
the error changes to:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 15, Size: 15
at java.util.ArrayList.rangeCheck(ArrayList.java:571)
at java.util.ArrayList.get(ArrayList.java:349)
at asmethods.lcc.turnIntoFlex(lcc.java:55)
at asmethods.lcc.calLcc(lcc.java:99)
at main2.main(main2.java:73)'
Where lcc is the class that contains the method turnIntoFlex that contains the piece of code I'm showing. The line 55 of "turnIntoFlex" corresponds to the first line of the loop, that is:
if (stopList.contains(def1.get(i))) { [...]
Comments:
The values of defA1 and defA2 are the definitions, respectively. i.e. def1 and def2, initially, are lists in which each separate element is a word. I can't check if these lists are being populated by printing them because the indexoutofboundsexception pops at the very moment the loop starts. However, I do print the values of the sizes of mdef, def1.size() and def2.size(), and the values turn out to be 13, or 15, showing that no list is empty before the "for" loop starts.
The mdef++ was something I added recently, not to exactly to solve this specific problem, but the error has been popping since before I added the mdef++ part. As I explained, The intention is to increase mdef++ when the shortest list is extended (but only when the short list is extended) so we iterate through all the words of the short list, and not more.
the problem your running in to is with the increment. try this:
for(int i = 0; i < mdef; i++){
if (stopList.contains(def1.get(i))) { //here I check if the first word of the first definition is also found in the stoplist.
if (!stopList.contains(def2.get(i))) { //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
mdef=Math.min(def2.size(),def1.size);
}
} else if (stopList.contains(def2.get(i))) { //this else if does the same than the previous one, but checks for the second definition instead of the first one. And adds blanks to def1 instead of def2 if necessary.
if (!stopList.contains(def1.get(i))) {
def1.add(i , " ");
mdef=Math.min(def2.size(),def1.size);
}
}
}
Let's look at this:
for(int i = 0; i < mdef; i++){
if (stopList.contains(def1.get(i))) { //here I check if the first word of the first definition is also found in the stoplist.
if (!stopList.contains(def2.get(i))) { //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
if(mdef == def2.size())
mdef++; //In case the shortest definition is the definition to which we just added spaces, we increment mdef++, because that space added increases the length of the shortest definition, and to iterate in this recenlty extended definiton, we have to increment the index with which we iterate.
}
}
}
forgetting about the else if for a second.
Suppose you started with both def1 and def2 of size 1. so mdef=1.
you went into the if(), added an entry to def2, and incremented mdef. Now
def1.size()=1
def2.size()=2
mdef=2
i=0
next iteration: i++ => i=1; i < mdef? true => enter the loop
def1.get(1) throws an exception, since you're going for element at index 1 in a list size 1.
This should work:
if (i < def1.size() && stopList.contains(def1.get(i))) {
...
}
and likewise in else if

Recursive Linked Lists in Java

I am working on an assignment that has me writing a java program to print out in reverse order the data contained in a linked list using recursion. So far this is what I have, it works but only on the final element in the list IE. it stops once it prints the last element.
public String reverse(IntNode head){
String result = "";
if(head.getLink() == null){
result += head.getData();
return result;
}
else if(head.getLink().getLink() == null){
result += head.getLink().getData();
head.removeNodeAfter();
return result;
}
else{
return reverse(head.getLink());
}
}
How would I get it to keep going through the list backwards up the recursive tree?
As others have pointed out, your solution is more complicated than it needs to be.
First, note that you don't need to (and probably don't want to) remove any items from the list in order to traverse it.
Second, rather than checking if the current node's link is null, you can actually check if the current link itself is null (nothing wrong with that so long as you don't attempt to dereference it). This simplifies the logic.
public String reverse(IntNode head) {
if (head == null)
return "";
else
return reverse(head.getLink()) + head.getData();
}
Or you could even write it like this:
public String reverse(IntNode head) {
return (head == null)? "" : reverse(head.getLink()) + head.getData();
}
When thinking about recursion, it's a good strategy to build up from the ground, until you hit interesting cases. At each step, try to reuse previous cases.
Q1. What is the reverse of an empty list? []
A1. An empty list. []
Q2. What is the reverse of a list with a single element? [ 1 ]
A2. The same list. [ 1 ]
Q3. What is the reverse of a list with two elements? [ 1 2 ]
A3. The first element, appended to the second element. [ 2 1 ] (Starting to get interesting)
Q4. What is the reverse of a list with three elements? [ 1 2 3 ]
A4. The first element, appended to the reverse of the list of the remaining elements. [ 3 2 ] + [ 1 ] = [ 3 2 1]
Now the pattern should start to be clear: the reverse of a list of N elements is the reverse of the last N - 1 elements with the first element appended).
What is our base case? From the above, it appears having a list of 1 or 0 elements. Look closer though, applying our pattern to a list of length 1, we see that [ 1 ] reversed is [] with the first element appended, ie [] + [ 1 ]. So really, our base case is just the empty list.
This code is more complicated than it needs to be. In this case the recursion can be broken down into 2 cases (or 2 execution paths the function might have):
Recursive case: this path calls itself so that recursion can start (or continue)
Base case: this path ends the recursion by returning without calling itself
Your code has 2 base cases, and it only needs 1. Think about all the different inputs you can call the function with:
head is null
head is an IntNode:
a. head.getLink() returns null
b. head.getLink() returns an IntNode:
head.getLink().getLink() returns null
head.getLink().getLink() returns an IntNode
You'll start to notice a pattern; once it's simplified there are really only 2 possible inputs:
head is null
head is an IntNode
If head is an IntNode, the function can call itself with head.getLink() (the recursive case) and it can be only those same 2 inputs, and this continues until head becomes null (the base case).
To answer your actual question, it only returns the last element's value because in the recursive case, you're not actually prepending the value of the current IntNode (i.e. head.getData()); you're just returning the result of the next reverse() call, which means it will recurse until it gets to the last element, and return just that element's value.

Categories