I have added data into ArrayList and now want to update that list be deleting some element from it.
I have element something like 1,2,3,4 in ArrayList of type CartEntry.
Code :
ArrayList<CartEntry> items = new ArrayList<CartEntry>();
public void remove(int pId)
{
System.out.println(items.size());
for(CartEntry ce : items)
{
if(ce.getpId() == pId)
{
items.remove(ce);
//System.out.println(items.get(1));
}
}
items.add(new CartEntry(pId));
}
CartEntry Code :
public long getpId() {
return pId;
}
Constructor :
public CartEntry(long pId) {
super();
this.pId = pId;
}
when I am trying this code it gives me an error:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
Here pId is the argument that specify that item should be deleted from items.
Suppose I want to delete item that have 2 data then what will I have to do ?
You are facing ConcurrentModificationException because you are doing two operations on the same list at a time. i.e looping and removing same time.
Inorder to avoid this situation use Iterator,which guarantees you to remove the element from list safely .
A simple example looks like
Iterator<CartEntry> it = list.iterator();
while (it.hasNext()) {
if (it.next().getpId() == pId) {
it.remove();
break;
}
}
There are at least two problems with your code:
you call remove on the collection you iterate over, that will cause a ConcurrentModificationException if you continue iterating after the remove.
There are two ways to fix this:
stop iterating after you found the object you want to remove (just add a break or a return) or
switch from the enhanced for-loop to using an Iterator and its remove method.
you add an element in your remove method, that's probably not what you want.
So I'd use this code (this assumes that there is only ever one CartEntry with a given id in the list):
public void remove(int pId)
{
for(CartEntry ce : items)
{
if(ce.getpId() == pId)
{
items.remove(ce);
return;
}
}
}
If the assumption with the unique id is not correct, then you'll need to use the Iterator approach:
public void remove(int pId)
{
Iterator<CartEntry> it = items.iterator();
while(it.hasNext())
{
CartEntry ce = it.next();
if(ce.getpId() == pId)
{
it.remove();
}
}
}
you have created an Arraylist of type carEntry. So you need to create an Iterator of type CarEntry
Iterator<CarEntry> it = items.iterator();
while(it.hasNext())
{
if(it.next().getPId == PId)
it.remove();
}
Implement .equals in CartEntry and then use ArrayList.remove(CartEntry) or loop through your array list, find the item with some condition, mark the index, and call ArrayList.remove(index) -- AFTER the loop
Try,
public void remove(int pId){
Iterator<CartEntry> it = items.iterator();
while(it.hasNext()) {
CartEntry entry = it.next();
if (entry.getpId() == pId) {
it.remove();
}
}
}
The enhanced-for(or for each) loop for iterating over an Expression which is a subtype of Iterable<E> or raw Iterable, basically equivalent to the following form:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableIdentifiers_opt TargetType Identifier = (TargetType) #i.next();
Statement
}
This is clearly stated in jls 14.14.2. The enhanced for statement section.
For your context the Expression is an ArrayList. the iterators returned by ArrayList's iterator method is fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.
use an Iterator instead and use it's own remove() method:
Iterator<E>iterator = list.iterator();
while(iterator.hasNext())
if(iterator.next().equals(E))
iterator.remove();
Related
I was recently asked about the question that how to create a Java Iterator for 2D Array, specifically how to implement:
public class PersonIterator implements Iterator<Person>{
private List<List<Person>> list;
public PersonIterator(List<List<Person>> list){
this.list = list;
}
#Override
public boolean hasNext() {
}
#Override
public Person next() {
}
}
1D array is pretty straightforward by using a index to track the position, any idea about how to do it for 2D lists.
In the 1D case you need to keep one index to know where you left, right?
Well, in the 2D case you need two indices: one to know in which sub-list you were working, and other one to know at what element inside that sub-list you left.
Something like this? (Note: untested)
public class PersonIterator implements Iterator<Person>{
// This keeps track of the outer set of lists, the lists of lists
private Iterator<List<Person>> iterator;
// This tracks the inner set of lists, the lists of persons we're going through
private Iterator<Person> curIterator;
public PersonIterator(List<List<Person>> list){
// Set the outer one
this.iterator = list.iterator();
// And set the inner one based on whether or not we can
if (this.iterator.hasNext()) {
this.curIterator = iterator.next();
} else {
this.curIterator = null;
}
}
#Override
public boolean hasNext() {
// If the current iterator is valid then we obviously have another one
if (curIterator != null && curIterator.hasNext()) {
return true;
// Otherwise we need to safely get the iterator for the next list to iterate.
} else if (iterator.hasNext()) {
// We load a new iterator here
curIterator = iterator.next();
// and retry peeking to see if the new curIterator has any elements to iterate.
return hasNext();
// Otherwise we're out of lists.
} else {
return false;
}
}
#Override
public Person next() {
// Return the current value off the inner iterator if we can
if (curIterator != null && curIterator.hasNext()) {
return curIterator.next();
// Otherwise try to iterate along the next list and retry getting the next one.
// This won't infinitely loop at the end since next() at the end of the outer
// iterator should result in an NoSuchElementException.
} else {
curIterator = iterator.next();
return next();
}
}
}
I have the following Node Class
Class Node {
private int id;
public int getId() {
return this.id;
}
}
and then create a TreeSet with the Nodes. Next I wanted to find and return a Node object based on id matching. However, every time the findNode() function is returning the next-to-next Node not the next one. I understand it is because of calling the iterator.next() twice. How can call it only once to check with the id value as well as return the object reference. I also tried with by creating a temporary Object reference but again it was the same result.
Class NodeSet {
Set<Node> set = new TreeSet<Node>();
public Node findNode(int id) {
Iterator<Node> iterator = set.iterator();
while(iterator.hasNext()) {
if(iterator.next().getId() == id)
return iterator.next();
}
return null;
}
}
Edit: The solution proposed here is logarithmic (unlike the accepted answer) and hence is much faster when the number of nodes in a treeset is large.
There is no get method in the Set interface which the class TreeSet implements. Keeping in mind that there exists a complete ordering between the elements of a treeset, a three line hack is as follows:
Object search(TreeSet treeset, Object key) {
Object ceil = treeset.ceiling(key); // least elt >= key
Object floor = treeset.floor(key); // highest elt <= key
return ceil == floor? ceil : null;
}
Class NodeSet {
Set<Node> set = new TreeSet<Node>();
public Node findNode(int id) {
Iterator<Node> iterator = set.iterator();
while(iterator.hasNext()) {
Node node = iterator.next();
if(node.getId() == id)
return node;
}
return null;
}
}
The issue happens here:
while(iterator.hasNext()) {
if(iterator.next().getId() == id)
return iterator.next();
}
You call twice iterator.next in the same loop explaining the "next-to-next" issue.
Make a local variable to still reach the same element or better: use the for loop if you have jdk >= 5:
for(Node node: set) {
if(node.getId() == id)
return node;
}
As #JB Nizet suggests in his comment above, a simple Map already implements your code logic by essence, and thus would better fit than a TreeSet and manual check.
More precisely, a TreeMapsorted on Nodes would be relevant. (since it sounds you need the order aspect)
I want to delete duplicate elements and therefore iterate through a ArrayList and compare two consecutive elements. (Persons are comparable)
ArrayList<Person> persons = getHelper().findAllPersons();
Collections.sort(persons);
ListIterator<Person> it = persons.listIterator();
if(it.hasNext()) {
Person tmp = it.next();
while(it.hasNext()) {
if(tmp.getLastDiscovered() == it.next().getLastDiscovered()) {
getHelper().delete(tmp);
}
tmp = it.next();
}
}
I get a NoSuchElementException at tmp = it.next();
Shouldn't the while(it.hasNext()) prevent that?
The problem is you are calling it.next() twice, which will advance the iterator two times.
You should store the value to avoid repeating the side-effect.
Person person = it.next();
if (tmp.getLastDiscovered() == person.getLastDiscovered()) {
getHelper().delete(tmp);
}
tmp = person;
Alternatively, you could use the for-each loop to avoid needing to interact with the iterators (I assume all Person are not null):
Person tmp = null;
for (Person person : persons) {
if (tmp != null && tmp.getLastDiscovered() == person.getLastDiscovered()) {
getHelper().delete(tmp);
}
tmp = person;
}
You're calling it.next() twice (potentially) for each it.hasNext() call, hence your error.
If you want to remove duplicates, why not just populate a TreeSet (providing the appropriate Comparator) with your list ? The semantics of a Set are such that you'll have a distinct set of elements.
If you're using JDK 1.5.0 or later (which you most likely are, since it was released in 2004), you can use a foreach loop to obviate the iterator altogether, greatly simplifying the code.
ArrayList<Person> persons = getHelper().findAllPersons();
Collections.sort(persons);
for (Person person : persons) {
if(tmp.getLastDiscovered() == person.getLastDiscovered()) {
getHelper().delete(tmp);
}
}
while(it.hasNext()) {
if(tmp.getLastDiscovered() == it.next().getLastDiscovered()) {
getHelper().delete(tmp);
}
After that 'while' you are coming to end of the list. Then when it hasn't got next value, you are calling the line below.
tmp = it.next();
That gives you an exception.
I have an ArrayList that contains some object, such as User, and each object has a name and password property. How can I delete only the User object that has a specific 'name' from this ArrayList?
Iterator<User> it = list.iterator();
while (it.hasNext()) {
User user = it.next();
if (user.getName().equals("John Doe")) {
it.remove();
}
}
You could use something like this:
// If you are using java 8
userList.removeIf(user-> user.getName().equals("yourUserName"));
// With older version
User userToRemove = null;
for(User usr:userList) {
if(usr.getName().equals("yourUserName")) {
userToRemove = usr;
break;
}
}
userList.remove(userToRemove);
Another thought: If User class can be uniquely defined by the username and if you override equals with something like:
public boolean equals(Object arg0) {
return this.name.equals(((user) arg0).name);
}
You can remove the User without iterating through the list . You can just do :
list.remove(new User("John Doe"))
You are probably faced with the ConcurrentModificationException while trying to remove object from the List. An explanation for this exception is that the iterator of the ArrayList is a fail-fast iterator. For example, it will throw an exception (fail) when it detects that its collection in the runtime has been modified. The solution to this problem is to use the Iterator.
Here is a simple example that demonstrate how you could iterate through the List and remove the element when specific condition is met:
List<User> list = new ...
for (Iterator<User> it = list.iterator(); it.hasNext(); ) {
User user = it.next();
if (user.getUserEmail().equals(currentUser.getUserEmail())) {
it.remove();
}
}
Recommended way to solve this problem is:
ArrayList<User> list = new ArrayList<User>();
list.add(new User("user1","password1"));
list.add(new User("user2","password2"));
list.add(new User("user3","password3"));
list.add(new User("user4","password4"));
Iterator<String> iter = list.iterator();
while (iter.hasNext())
{
User user = iter.next();
if(user.name.equals("user1"))
{
//Use iterator to remove this User object.
iter.remove();
}
}
Using Iterator to remove an object is more efficient than removing by simply typing ArrayList(Object)
because it is more faster and 20% more time saving and a standard Java practice for Java Collections.
You could:
loop over the list with an iterator
check if each item in your list is the right user (checking the name)
if it is, use the remove method of the iterator.
Just search through the ArrayList of objects you get from the user, and test for a name equal to the name you want to remove. Then remove that object from the list.
Your code might look like this:
List<User> users = new ArrayList<User>();
public void removeUser(String name){
for(User user:users){
if(user.name.equals(name)){
users.remove(user);
}
}
}
ArrayList<User> userList=new ArrayList<>();
//load data
public void removeUser(String userName){
for (User user: userList){
if(user.getName()equals(userName)){
userList.remove(user);
}
}
}
I was just wondering what the easiest way to iterate over a set indefinitely, i.e. when it reaches the end it next(); calls the first object. I'm assuming that this is not an already predefined function in Java, so just looking for the easiest way to implement this in Java.
There's a method in the excellent Google Collections library which does this:
Set<String> names = ...;
Iterable<String> infinite = Iterables.cycle(names);
(I can't recommend the Google Collections library strongly enough. It rocks very hard. I'm biased as I work for Google, but I think pretty much every Googler writing Java would tell you how useful the collections are.)
Iterator it = mylist.iterator();
while (it.hasNext())
{
MyType t = (MyType)it.next();
// do something
if (!it.hasNext())
it = mylist.iterator();
}
Try EndlessIterator from Cactoos:
Iterator<String> names = new EndlessIterator<>("John");
It will always return "John" and will never end.
Also, check EndlessIterable, which implements Iterable and does the same.
If you're making the iterator, in the next method you can have an if condition that checks if there's another object in the list. If there is, then you return that object, if there isn't then you go back to the start of the list and return that object.
This is what I can think of...
iterator = set.getIterator
//other code
if (iterator.hasNext())
//do code here
else
iterator = set.getIterator();
How about ?
List<String> list = // ArraysList
Interator<String> it = null;
while(true) {
it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
If you don't want to use Guava but still want a reusable solution:
public static class CyclicIterator<E, C extends Collection<E>> implements Iterator<E> {
final private C mElements;
private Iterator<E> mIterator;
public CyclicIterator(C elements) {
mElements = elements;
mIterator = elements.iterator();
}
#Override
public boolean hasNext() {
if (! mIterator.hasNext()) {
mIterator = mElements.iterator();
}
return mIterator.hasNext();
}
#Override
public E next() {
if (! mIterator.hasNext()) {
mIterator = mElements.iterator();
}
return mIterator.next();
}
}
Note: this doesn't support the remove() method but it could easily be added if needed. Also it's not thread safe.
I think what you want never help You can do anything with your iterator that's easy but you must be carefull with any new thing you add im not used with this style but this is what you want though :
if (! It.hasNext() )
{
while ( It.hasPrevious() )
{
It = It.Previous();
}
} else {
It = It.Next();
}
This way is nothing if your really interested you should instead make next pointer of the last to the first always when pushing a new list.
std jdk:
Iterable<String> infinite = Stream.generate(names.stream()).flatMap(e -> e).iterator()