java.util.ConcurrentModificationException error when using iterator? - java

Why am I getting this problem when trying to print it out? What I'm trying to do is display out the name that was placed in the array.
ArrayList <Employee> empArray = new ArrayList();
LinkedList empyrIncm = new LinkedList();
ListIterator li = empyrIncm.listIterator();
DecimalFormat df = new DecimalFormat ("#, ##0.00");
for (int i = 0; i<empArray.size(); i++)
{
double yrIncm = empArray.get(i).getSalary() * 12;
if (yrIncm > 80000)
{
empyrIncm.add (new String (empArray.get(i).getEmpName()));
while(li.hasNext())
{
System.out.println ("\nName : " + li.next() + "\nTotal yearly income : " + df.format (yrIncm));
}
}
else
{
foundyrIncm = false;
}
}
From what I know, the iterator I used is to display out the name "one-by-one" without the "comma" when more input are added to the array. Means, without the use of iterator, it will display out by default
Name : Object1, Object 2, Object 3, Object 4
Total yearly income : 123
I don't want that comma, instead I want the name to be display out one by one with their yearly income. Any help would be appreciated.

Try initializing the ListIterator just outside the while loop.
ArrayList <Employee> empArray = new ArrayList();
LinkedList empyrIncm = new LinkedList();
DecimalFormat df = new DecimalFormat ("#, ##0.00");
for (int i = 0; i<empArray.size(); i++)
{
double yrIncm = empArray.get(i).getSalary() * 12;
if (yrIncm > 80000)
{
empyrIncm.add (new String (empArray.get(i).getEmpName()));
ListIterator li = empyrIncm.listIterator();
while(li.hasNext())
{
System.out.println ("\nName : " + li.next() + "\nTotal yearly income : " + df.format (yrIncm));
}
}
else
{
foundyrIncm = false;
}
}

You are adding element to the list here:
empyrIncm.add (new String (empArray.get(i).getEmpName()));
while you are iterating the list here:
System.out.println ("\nName : " + li.next() + "\nTotal yearly income : " + df.format (yrIncm));
The iterator in java are Fail-fast. It will not allow you to update the list while iterating over it.
You need to use CopyOnWriteArrayList instead of LinkedList. Normally CopyOnWriteArrayList is very expensive because it involves costly Array copy with every write operation. Use the below statement.
CopyOnWriteArrayList empyrIncm = new CopyOnWriteArrayList();
Also your iterator getting call will be postponed until you need it. Just before the while loop.
ListIterator li = empyrIncm.listIterator();

You cant do following two line's activity together i.e.read & write together with regular fail-fast iterator data structures :-
empyrIncm.add (new String (empArray.get(i).getEmpName()));
while(li.hasNext())
If you want to do both read & write together then do either of the following :-
empyrIncm.add (new String (empArray.get(i).getEmpName()));
ListIterator li = empyrIncm.listIterator();
while(li.hasNext())
OR
Use CopyOnWriteArrayList instead of LinkedList/ArrayList.
Now if you try to print any list then default implementation provided by API prints all element in list by comma seperated, hence the output you getting.

Related

Discard elements of a String Array matching a specific criterion and Join them together without using indices

I have a string array of full names with different surnames, i.e.
String[] tempArray = {"rakesh bhagat", "mayur suryavanshi", "prathamesh ambre", "akash tare", "abhi ingle", "rutvik patil"};
I want to create a new string of all names except one name, i.e.
temp = "rakesh bhagat, mayur suryavanshi, prathamesh ambre, akash tare, abhi ingle, rutvik patil";
So here I want to remove "mayur suryavanshi" from array without using index because I don't know index of that item, but I have certain condition like
if(tempArray[i].endsWith("suryawanshi")){}
Which I can use in for loop.
I tried to make new string with removing those item in for loop
String result = joiner.toString();
String temp = null;
for (int i = 0; i < tempArray.length; i++) {
if (tempArray[i].endsWith("suryavanshi")) {
continue;
}
if (temp == null) {
temp = tempArray[i];
} else {
temp = temp + ", " + tempArray[i];
}
}
Avoid concatenating string in the loop, each concatenation str1 + str2 in a new string stored as a separate object. As the consequence of this, lots of intermediate strings which you don't need would be created.
Use StringBuilder or other built-in mechanisms when you need to join together more than just a couple of strings.
Collectors.joining()
It can be done with Stream API using built-in Collector joning():
String[] tempArray = {"rakesh bhagat", "mayur suryavanshi", "prathamesh ambre", "akash tare", "abhi ingle", "rutvik patil"};
String result = Arrays.stream(tempArray)
.filter(str -> !str.endsWith("suryavanshi")) // retain only elements which don't end with "suryavanshi"
.collect(Collectors.joining(", "));
StringJoiner
Alternatively, you can use a so-called enhanced for-loop (also known as for-each) and StringJoiner :
StringJoiner joiner = new StringJoiner(", ");
for (String str : tempArray) {
if (str.endsWith("suryavanshi")) continue;
joiner.add(str);
}
String result = joiner.toString();

How to concat string values in array list

I need to print all arraylist values at a time using concat.
Here is my code:
ArrayList<String> lst = new ArrayList<String>();
lst.add("hi");
lst.add("hello");
Iterator<String> itr = lst.iterator();
String result = null;
while(itr.hasNext()) {
Object element = itr.next();
result = element + " ";
}
System.out.println(result);
The expected result should be hi hello.
The current output however is hello (there is also a whitespace at the end).
Please prefer the List interface to the ArrayList concrete type. Assuming you are using Java 8+, you might use a Stream and Collectors.joining (and Arrays.asList) like
List<String> lst = Arrays.asList("hi", "hello");
String r = lst.stream().collect(Collectors.joining(" "));
System.out.println(r);
Which outputs
hi hello
As requested.
The error in your code is pretty small. In each iteration you assign a value to the result variable. However instead of updating your existing content you just erase it and enter a new value.
You do result = element + " ". But it should be something like result = result + element + " " or the same in short:
result += element + " ";
This way the first iteration will save hi in it and after that hello gets appended resulting in hi hello (instead of overriding the content of the first iteration).
Note that it now also has the whitespace at the end. You could delete it with result = result.substring(0, result.length() - 1). Or not add it in the last iteration, but then you need to count the iterations.
Please note that Java has a class StringJoiner that does exactly what you want, joining some elements together and also using a delimiter like whitespace. You use it like this:
StringJoiner sj = new StringJoiner(" ");
while(itr.hasNext()) {
Object element = itr.next();
sj.add(element);
}
String result = sj.toString();
Also note that since Java 8 there is an even shorter version of it:
String result = String.join(" ", list);

Check if array-list contains a certain string and integer

let's say i have this array list
List<String> Speach2R = new ArrayList<>();
Speach2R.add(0, "Hello");
Speach2R.add(1, "yes");
Speach2R.add(2, "Hi");
and i wanna say
if (messages.contains(any of Speach2R strings){
said = true;
}
also i want to find the int of the founded message, like if message "Hi" exists
int MessageNumber = 2
If you message is like a sentence, you need to iterate over the word of the List
Set<Integer> indexes = new TreeSet<>();
String message = "Hi, my name is john, and Hello";
for (String word : Speach2R){
if (message.contains(word)){
indexes.add(Speach2R.indexOf(word));
}
}
It will iterate over the word of the List, and store in a Set all the indexes of the word it founds
System.out.println("Your message contains :");
for (Integer i : indexes){
System.out.println(Speach2R.get(i) + ", at index " + i);
}
And with that you will print all the words found + their index in the List
You can use the ArrayList#contains method since your List consists of Strings and ArrayList#indexOf for the index.
It would look like this
String message = "yes";
boolean found = false;
int index = -1;
if(speach2R.contains(message)){
found = true;
index = speach2R.indexOf(message);
}
With the java 8 Stream API, you can do something like this :
messages.stream().filter( Speach2R::contains ).findAny().isPresent()

listing arraylist items inside another arraylist?

I just used the
ArrayList <ArrayList<String>> list = new ArrayList<ArrayList<String>>();
method for the first time and the output wasn't exactly in the way I wanted it to be.
I'm trying to make lists of different students and sorting them by what grade they're in. But, I am also trying to have a list that displays all the students, regardless of their grade. So this is the code that I was using:
ArrayList <ArrayList<String>> allStudents = new ArrayList<ArrayList<String>>();
ArrayList <String> gradeNines = new ArrayList();
ArrayList <String> gradeTens = new ArrayList();
ArrayList <String> gradeElevens = new ArrayList();
ArrayList <String> gradeTwelves = new ArrayList();
boolean firstSelection = true;
public void grade(String a, String b, ArrayList c)
{
a = jComboBox1.getSelectedItem() + "";
if (a.equals(b))
{
studentOutput.setText("");
int x = 0;
for (int indexNum = 0; indexNum < c.size(); indexNum++)
{
x = indexNum + 1;
studentOutput.append(num + ". " + c.get(indexNum) + "\n");
}
}
}
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {
String studentGrade = jComboBox1.getSelectedItem() + "";
String all = "All Grades";
String nine = "Grade Nine";
String ten = "Grade Ten";
String eleven = "Grade Eleven";
String twelve = "Grade Twelve";
if (firstSelection)
{
Collections.addAll(allStudents, gradeNines, gradeTens, gradeElevens, gradeTwelves);
Collections.addAll(gradeNines, "Oscar", "Justin",....);
Collections.addAll(gradeTens, "Austin", "Jacob", "Evie"....);
Collections.addAll(gradeElevens, "Olivia", "Elizabeth"...);
Collections.addAll(gradeTwelves, "Ryan", "Jade"...);
firstSelection = false;
}
grade(studentGrade, all, allStudents);
grade(studentGrade, nine, gradeNines);
grade(studentGrade, ten, gradeTens);
grade(studentGrade, eleven, gradeElevens);
grade(studentGrade, twelve, gradeTwelves);
But the way this outputted, it was like:
[Oscar, Justin] 2. [Austin, Jacob, Evie] 3. [Olivia, Elizabeth] 4. [Ryan, Jade]
Is there a way to make it so that it outputs so that it shows each name individually like:
Oscar 2. Justin 3. Austin 4. Jacob ...
Firstly, these type of "grouping" problems are better handled using a Map (HashMap or an ordered implementation).
You could have the grades as the key and the list of student names as the values. That would feel as a better and easier way to handle collection data than a nested ArrayList.
Regarding your question,
Is there a way to make it so that it outputs so that it shows each name individually
No. These are separate ArrayLists. You will need to add/display them together, explicitly.
Further, I suggest you use the groupingBy function of Streams in Java 8. That will fit your use case very well.
With Streams, you could choose to display all items together OR group them by grades and display based on the chosen crteria(grade).
See this SO answer: https://stackoverflow.com/a/30202075/599851

Arraylist replace each element with first occurance of some string

I have an arraylist like below
List<String> list = new ArrayList<String>();
list.add("P Pro Rata(Average Cost w/Tax Lots)");
list.add("A apple is good");
list.add("B ball is nice");
list.add("C cat is not there");
I want the first space of each element in the array list should be replaced with : operator(only first space and for each element)
so output should be
A:apple is good
B:ball is nice
C:cat is not there
I have a solution which iterates and creates new element and add it to new list and using that new list
can any one come up with best solution ?
Try this:
for(int i=0;i<list.size();i++) {
list.set(i,list.get(i).replaceFirst(" ", ":"));
}
You can use indexOf to find the first occurance of a space in the strings as such:
for (String s : list) {
int index = s.indexOf(" ");
String prefix = s.substring(0, index);
String suffix = s.substring(index+1);
System.out.println(prefix + ":" + suffix);
}
Use for each to iterate array list and replaceFirst will help you replace first char
int i=0;
for (String s : list){
list.set(i,s.replaceFirst(" ", ":"));
i++;
}

Categories