Elements are not being removed from ArrayList - java

I am trying to remove elements that do not contain a specific string from an arrayList but with no luck. I am using the following code:
ArrayList<String> classes = ClassesRetrieval.getYagoClasses();
Iterator<String> it = classes.iterator();
while(it.hasNext()){
if(it.next().contains("yago")){
it.remove();
}
}
for(String i : classes){
System.out.println(i);
}
I also tried
for(int i=0;i<classes.size();i++){
if(!classes.get(i).contains("yago")){
classes.remove(i);
}
}
for(String i : classes){
System.out.println(i);
}
but with no luck..

I tested you first code on a list I created myself. It worked, but if you want to remove Strings that don't contain "yago", you are missing a !.
ArrayList<String> classes = ClassesRetrieval.getYagoClasses();
Iterator<String> it = classes.iterator();
while(it.hasNext()){
if(!it.next().contains("yago")){
it.remove();
}
}
for(String i : classes){
System.out.println(i);
}

First of all, remove '!' in your second code if(!classes.get(i).contains("yago")), and i think it should work.
If it won't, give some base code of ClassesRetrieval.getYagoClasses();, please.

Using for loops to remove elements is really not recommended. Consider having two consecutive strings, both of which contain "yago". It will remove the first one, increment i and skip the second string (since it now has the index of the first string).
Try a while loop where you increment only if you don't remove the element (or, if you hate branching, reverse the for loop from greater to smaller).
As for your first example, right now it removes all those that do contain "yago". If you put a ! before the condition it should work properly.

I don't see anything wrong with your syntax/logic. However, it is possible that the condition
!classes.get(i).contains("yago")
Is not being met. To test whether this is true, I would print something if the condition yields true. For example:
for(int i=0;i<classes.size();i++){
if(!classes.get(i).contains("yago")){
classes.remove(i);
System.out.println("Condition Met");
}
}
You can even print the deleted element like this:
for(int i=0;i<classes.size();i++){
if(!classes.get(i).contains("yago")){
System.out.println(classes.remove(i));
}
}
I hope you find this helpful.

The second piece of code you showed should work. Why are you using the negation (!) in your for loop?
I think that what you wanted is:
for(int i=0; i<classes.size(); i++){
if(classes.get(i).contains("yago")){
classes.remove(i);
}
}
The problem with this approach is that when you remove an element from the list you change it's size. You could instead create an empty ArrayList and keep adding new elements to it if it does not obey the condition:
List<String> tmp = new ArrayList();
for(String token : classes){
if(!token.contains("yago")){
tmp.add(token);
}
}
for(String i : tmp){
System.out.println(i);
}

It might make since to iterate in reverse to avoid index problems. Try something like this:
for(int i=classes.size()-1; i>=0; i--)
{
//get a string from list
String s = classes.get(i);
if(!s.contains("yago"))
{
//if the string does not contain yago, remove it
classes.remove(i);
}
}

Related

How can I remove Strings from an ArrayList which contain only whitespace characters?

I want to remove all strings in a list which contain only whitespace characters. I tried the following code, but some lines were not removed:
List<String> getarray = /* ... */;
for (int i = 0; i < getarray.size(); i++) {
if (getarray.contains(" ").getarray.contains(null)) {
getarray.remove(i);
} else {
System.out.println("a: " + getarray.get(i));
}
}
This does only work for certain inputs, can somebody help me understand why?
Here is a list of inputs which did not work as intended
First of all use some Iterator to iterate and perform your operation of removing elements from ArrayList.
Second to solve your problem of empty string , you could use trim() and isEmpty() methods
try below code:
Iterator<String> it = getarray.iterator();
while (it.hasNext()) {
String myValue = it.next();
if (myValue.trim().isEmpty()) {
it.remove();
} else {
System.out.println("a: " + myValue);
}
}
Use Iterators if you want to remove elements. According to Java docs:
Iterator takes the place of Enumeration in the Java Collections Framework. Iterators differ from enumerations in two ways:
Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
Method names have been improved
Try the following code:
Iterator<String> itr = getarray.iterator();
while (itr.hasNext()) {
String value = itr.next();
if (value.trim().isEmpty()) {
itr.remove();
} else {
System.out.println("a: " + value);
}
}
You misunderstand between element is empty or only composed of spaces AND element contain spaces :
So it's element.trim().isEmpty() instead of element.contains(" ");
.trim() removes spaces at start and at the ens of the String
So this will do your stuff, it will iterate over the list, and only keep the element which are not empty (or only compsed of spaces)
getarray = getarray.stream().filter(s -> !s.trim().isEmpty()).collect(Collectors.toList());
If you wan to print all after just do : getarray.forEach(System.out::println);

Java - Executing two corrosponding for loops at same time

I have two for loops written in java below. The first one grabs all the titles of news articles on a website, and the second one grabs all the links of the same new articles on the same website.
How do I make it so that when the first loop executes once, the second loop executes once, and then the first loop executes a second time, and the second one executes a second time, etc. I would really appreciate your help, thanks.
for( org.jsoup.nodes.Element element : elements1 ){
sendMessageRequest.setText(element.text());
sendMessage(sendMessageRequest);
System.out.print("sent message");
}
for( org.jsoup.nodes.Element element : elements2 ) {
sendMessageRequest.setText(element.text());
sendMessage(sendMessageRequest);
System.out.print("sent message");
}
I'm going to assume that elements1 and elements2 are some kind of Iterable<Element>, e.g. List<Element>.
First, remember that for (Element element : elements1) is just syntactic sugar for:
Iterator<Element> iter = elements1.iterator();
while (iter.hasNext()) {
Element element = iter.next();
// code here
}
Except that you don't have access to the Iterator.
So, if you want to iterate two different Iterable objects, do so the old-fashioned way:
Iterator<Element> iter1 = elements1.iterator();
Iterator<Element> iter2 = elements2.iterator();
while (iter1.hasNext() && iter2.hasNext()) {
Element element1 = iter1.next();
Element element2 = iter2.next();
// code here
}
If the two Iterable objects are not the same length, the loop will only iterate until the shorter one has been exhausted. Extra elements in the other one will simply be ignored.
If elements1 and elements2 are guaranteed to have the same length, just iterate through them into one loop:
for (int i = 0; i < elements1.length; i++) {
processMessageRequest(elements1[i]);
processMessageRequest(elements2[i]);
}
Using a new method processMessageRequest to make your code more DRY:
private void processMessageRequest(Element e) {
sendMessageRequest.setText(e.text());
sendMessage(sendMessageRequest);
System.out.println("sent message");
}
I'm not sure what the scope of sendMessageRequest is... but with some tweaking this way could work.

How to additionally iterate inside the loop for(String s : st) in java?

I am iterating over a vector of string as:
for(String s : st){
while(s.equals("a")) //just an example, not exactly this required
{
//go to next element : How to do this?
}
System.out.println(s);
}
How to iterate over next elements within the for(:) loop?
EDIT:
As many asked the logic of while,
the vector of string is basically containing single words of a sentence and I have to collapse Noun Phrases in the sentence, e.g. if there is a sentence like "Robert Sigwick is going home". so right now st[0] has "Robert" and st[1] has "Sigwick". After the processing I have to make st[0] = "Robert Sigwick".
So my code is somewhat like:
for(String s : st){
string newEntry = "";
while(getPOS(s).equals("NNP"))
{
newEntry += s;
// HERE I WANT THE HELP : something like s = getNext();
}
if(!newEntry.equals(""))
result.add(newEntry);
}
for(String s : st){
if(s.equals("a")) //just an example, not exactly this required
{
//go to next element : How to do this?
continue;
}
System.out.println(s);
}
Use loop labels with continue
OUTER:
for(String s : st){
while(s.equals("a")) //just an example, not exactly this required
{
//go to next element : How to do this?
continue OUTER;
}
System.out.println(s);
}
NOTE: The loop label is only necessary if you have a nested loop. If the while should be an if-statement then a simple continue; will work.
also if it's an if-statement there could be even better ways. Consider:
for(String s : st){
if(!s.equals("a")) //just an example, not exactly this required
{
System.out.println(s);
}
}
The problem here is that the whole method goes one level deeper. It's a preference thing.
More on loop labels: "loop:" in Java code. What is this, why does it compile?
You need to explain why you need a while loop. You cannot go to next element this way.

get value that occurs more than one in a list?

What are the the best methods to get values that occur more than once in a large list of words without slowing my run time?. My file contains 1xx,xxx words and I put them into a linked list. Now, I want to get only the words that occur more than once out of that list.
For example, if a list contains:
....This is is is just a test test....
I want to get is and test and put them into another list using an iterator.
I don't know if my code is right, and I think that this is not the best solution to approach for this problem.
for(int i = 0; i < word.size(); i++) {
Word s = word.get(i);
Word s1 = word.get(i+1);
if(s.equals(s1)) {
newWord.add(s);
}
}
Put them all into HashSet instead of list and check the return value of add() method.
HashSet<Word> wordSet = new HashSet<>();
for(int i = 0; i < word.size(); i++) {
if(!wordSet.add(word.get(i)){
//Found duplicate
}
}
Note that you can also do it during/instead of creation of the list of the words.
Build a hashmap with the word as key and it count as value.
for(each word in list)
{
count = 1;
if(map.contains(word))
{
count = map.get(word);
}
else
count = 1;
map.put(word,count);
}
Then iterate over the hashmap and check if values is 1, and add the word to your list.
If you can sort the list, then finding duplicates is quick and easy.

Finding the powerset of a String

I'm trying to write a java method for finding the subset of a string but I keep getting a runtime error I have been unable to debug. Here is the code:
public static List<String> subset(String m, List<String> list){
if (m.length() <= 1){
list.add(m);
return list;
}
else{
String letter = m.substring(0,1);
String rest = m.substring(1,m.length());
for (String x : subset(rest,list)){
list.add(letter + x);
}
list.add(letter);
return list;
}
}
Your problem is that in your for loop, you're iterating through a list that's constantly changing. This gives you a ConcurrentModificationException.
It's better if you make a copy of your list first, before you try to iterate through it. You want something like this in place of your for loop.
List<String> copy = new ArrayList<String>(subset(rest,list));
for (String x : copy){
list.add(letter + x);
}
This works, of course (yes, I've tested it), but it's a bit confusing in the way that you've added SOME elements by recursion and OTHERS by iteration. I think a re-design would be a good idea.

Categories