Getting Concurrent Modification Exception while adding elements to ArrayList recursively.
import java.util.*;
public class Hello {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String str = sc.next();
System.out.println(gss(str));
}
public static ArrayList<String> gss(String str) {
if(str.length() == 0){
ArrayList<String> list = new ArrayList<String>();
list.add("");
return list;
}
ArrayList<String> list = gss(str.substring(1));
for(String temp : list){
list.add(str.charAt(0)+temp); // Problem
}
return list;
}
}
Solution: To just form new ArrayList at each call stack and return it.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String str = sc.next();
System.out.println(gss(str));
}
public static ArrayList<String> gss(String str) {
if(str.length() == 0){
ArrayList<String> list = new ArrayList<String>();
list.add("");
return list;
}
ArrayList<String> list = gss(str.substring(1));
ArrayList<String> listToReturn = new ArrayList<>();
for(String temp : list){
listToReturn.add(temp);
}
for(String temp : list){
listToReturn.add(str.charAt(0) + temp);
}
return listToReturn;
}
}
I have recently come across this blog.
Which says, It uses a transient variable called modCount, which keeps track of how many times a list is modified structurally. Structural modifications are those that change the size of the list, which may affect the progress of iteration and may yield incorrect results. Both Iterator and ListIterator uses this field to detect unexpected change. Other methods of List which structurally modify List also uses this method e.g. add(), remove().
Cause: The real cause of ConcurrentModficationException is inconsistent modCount. When you are iterating over ArrayList then Iterator's next() method keep track of modCount. If you modify the collection by adding or removing element then modCount will change and it will not match with the expected modCount, hence Iterator will throw ConcurrentModificationException.
Related
I have to write a method called removeDups that accepts an ArrayList of Strings and returns a copy of the ArrayList with all the duplicates removed. I have to return a new ArrayList with no duplicate basically.
import java.util.ArrayList;
public class Duplicates {
public static ArrayList <String> removeDups(ArrayList<String> myArray) {
for (String item: myArray ) {
ArrayList <String> noDuplicate = new ArrayList <String>();
if (!noDuplicate.contains(item)) {
noDuplicate.add(item);
}else
;
return noDuplicate;
}
}
}
As a beginner coder, I am having trouble writing this code.
You need to modify few things to make it work (and to have cleaner code):
when you do not need ArrayList<String> you should work with interface List<String>
you should initiate noDuplicate array in the first line of method
you should check the condition !noDuplicate.contains(item) and if so just add item to noDuplicate list
rename the method from removeDups to removeDuplicates
Working code:
public static List<String> removeDuplicates(List<String> myArray) {
List<String> noDuplicate = new ArrayList<>();
for (String item : myArray) {
if (!noDuplicate.contains(item)) {
noDuplicate.add(item);
}
}
return noDuplicate;
}
If you will take a look on Java streams you can do the same thing using:
List<String> noDuplicate = myArray.stream()
.distinct()
.collect(Collectors.toList());
My excercise is:
Create the method lengths that gets a list of String variables as a parameter and returns an ArrayList that contains the lengths of the Strings in the same order as the original list.
And my code:
import java.util.ArrayList;
public class Test {
public static ArrayList<Integer> lengths(ArrayList<String> strings) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (String item : strings) {
System.out.print(item.length());
}
return list;
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Dog");
list.add("Elephant");
list.add("Aligator");
list.add("Parrot");
ArrayList<Integer> stringLenghts = lengths(list);
System.out.println(stringLenghts);
}
}
And this program outputs
3386[]
Instead of
[3, 3, 8, 6]
Any idea where I do a mistake?
In your lengths() method, you are simply printing the length values.
But you are NOT adding the lengths to the ArrayList i.e., your stringLenghts list is empty (so printing as [] empty array), so change your code as shown below:
public static ArrayList<Integer> lengths(ArrayList<String> strings) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (String item : strings) {
list.add(item.length());//add length to list
}
return list;
}
Try this.
import java.util.ArrayList;
public class Test {
public static ArrayList<Integer> lengths(ArrayList<String> strings) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (String item : strings) {
list.add(item.length());
}
return list;
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Dog");
list.add("Elephant");
list.add("Aligator");
list.add("Parrot");
ArrayList<Integer> stringLenghts = lengths(list);
System.out.println(stringLenghts);
}
}
EDIT: In the lengths method, the list is being created but you are not adding any items to it. Now in the code abode for (String item : strings) { list.add(item.length()); } This adds the length of each string to the new ArrayList which you will return to the main method for printing.
Thanks
You need correct this body of cycle and add here the numbers
list.add(item.length());
between brackets.
Initially you are printing the length of each string from the loop
for(String item : strings) {
System.out.print(item.length());
}
which outputs : 3386 (no new line because of print)
After this empty ArrayList is printed because you are returning the empty arrayList object.
System.out.println(stringLenghts);
which outputs : [ ]
Solution :
You have to replace System.out.print(item.length());
with
list.add(item.length());
I have in mind the algorithm of my school-class program, but also difficulty in some basics I guess...
here is my code with the problem:
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
String allWords = System.getProperty("user.home") + "/allwords.txt";
Anagrams an = new Anagrams(allWords);
for(List<String> wlist : an.getSortedByAnQty()) {
//[..............];
}
}
}
public class Anagrams {
List<String> myList = new ArrayList<String>();
public List<String> getSortedByAnQty() {
myList.add("aaa");
return myList;
}
}
I get "Type mismatch: cannot convert from element type String to List"
How should initialise getSortedByAnQty() right?
an.getSortedByAnQty() returns a List<String>. When you iterate over that List, you get the individual Strings, so the enhanced for loop should have a String variable :
for(String str : an.getSortedByAnQty()) {
//[..............];
}
If the main method should remain as is, you should change getSortedByAnQty to return a List<List<String>>.
char[] cArray = "MYString".toCharArray();
convert the string to an array as above and then iterate over the character array to form a list of String as below
List<String> list = new ArrayList<String>(cArray.length);
for(char c : cArray){
list.add(String.valueOf(c));
}
This question already has answers here:
List.remove strange behaviour
(4 answers)
Closed 7 years ago.
I am learning Java's Collection framework. I wrote this little program to check why we can't use For-each to remove elements.
Code:
import java.util.ArrayList;
class intro{
public static void main(String args[]){
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
for(String name:names){
names.remove(name);
}
for(String name:names){
System.out.println(name);
}
}
}
Outputs:
Saxena
And
import java.util.ArrayList;
class intro{
public static void main(String args[]){
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
names.add("Arvind");
for(String name:names){
names.remove(name);
}
for(String name:names){
System.out.println(name);
}
}
}
Throws:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at intro.main(intro.java:15)
How come just the addition of one more element to collection is causing the error?
Normally when you remove an element from a collection while looping over the collection, you'll get a ConcurrentModificationException. This is partially why the Iterator interface has a remove() method. Using an iterator is the only safe way to modify a collection of elements while traversing them.
The code would go something like this:
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
names.add("Arvind");
for (Iterator<String> iterator = name.iterator(); iterator.hasNext();) {
String string = iterator.next();
if (string.isEmpty()) {
iterator.remove();
}
}
I know how to use generics in java but if an instance is given as
List<someclass> ai = new List<someclass>();
How can I use the list in this case? How can I access and modify elements in the class?
Please provide an example.
You can use it mostly like any non-generic list.
Here is an example with a list of Strings that shows inserting, getting and deleting elements as well as checking for their existence:
package example;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
// Get/extract the first element
// You can then call methods on
// that element, e.g. list.get(0).toUpperCase(...)
String firstElement = list.get(0);
System.out.println("First Element: " + firstElement);
// Remove the first element
list.remove("foo");
firstElement = list.get(0);
System.out.println("First Element after delete: " + firstElement);
// Check whether the list contains an object
if (list.contains("bar")) {
System.out.println("List contains bar.");
} else {
System.out.println("List doesn't contain bar.");
}
}
}
Outputs:
First Element: foo
First Element after delete: bar
List contains bar.
You can use generics in method parameters to only accept lists that contain certain types of elements:
package example;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
printAll(list);
}
public static void printAll(List<String> list) {
for (String str : list) {
System.out.println(str);
}
}
}
Outputs:
foo
bar
The following however is invalid, because you would try to insert an Integer into a Strings-only list:
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add(1);
}
The line of code you provided is not correct. List is an interface and interfaces cannot be instantiated. If you want to define a variable of type List<ClassName>, you have to initialize it with a constructor of a subclass. The most common subclass for the List<> interface is the ArrayList<> class. So your line of code should be:
List<SomeClass> ai = new ArrayList<SomeClass>();
Here you can find more information for interfaces.