Related
I have an ArrayList of Items and I want to be able remove one Item from the list by entering only one Item attribute, for example its number (int ItemNumber). I also wanna do the same when I check Item quantities.
These are my equals() & contains() methods, do I need to make any changes here?
public boolean contains(T anEntry) {
boolean found = false;
for (int index = 0; !found && (index < numberOfEntries); index++) {
if (anEntry.equals(list[index]))
found = true;
}//end for
return found;
} // end contains
public boolean equals(Object object){
Item item = (Item) object;
if (itemNo == item.itemNo)
return true;
return false;
}
If you change the class Item equals() and compareTo() methods, so that they check only one object field, such as a quantity, it could result in strange behavior in other parts of your application. For example, two items with different itemNo, itemName, and itemPrice, but with the same quantities could be considered equal. Besides, you wouldn't be able to change the comparison attribute without changing the equals() code every time.
Also, creating a custom contains() method makes no sense, since it belongs to the ArrayList class, and not to Item.
If you can use Java 8, a clean way to do it is to use the new Collection's removeIf method:
Suppose you have an Item class with the num and name properties:
class Item {
final int num;
final String name;
Item(int num, String name) {
this.num = num;
this.name = name;
}
}
Given a List<Item> called items and an int variable called number, representing the number of the item you want to remove, you could simply do:
items.removeIf(item -> item.num == number);
If you are unable to use Java 8, you can achieve this by using custom comparators, binary search, and dummy objects.
You can create a custom comparator for each attribute you need to look for. The comparator for num would look like this:
class ItemNumComparator implements Comparator<Item> {
#Override
public int compare(Item a, Item b) {
return (a.num < b.num) ? -1 : ((a.num == b.num) ? 0 : 1);
}
}
Then you can use the comparator to sort and search for the desired elements in your list:
public static void main(String[] args) {
List<Item> items = new ArrayList<>();
items.add(new Item(2, "ball"));
items.add(new Item(5, "cow"));
items.add(new Item(3, "gum"));
Comparator<Item> itemNumComparator = new ItemNumComparator();
Collections.sort(items, itemNumComparator);
// Pass a dummy object containing only the relevant attribute to be searched
int index = Collections.binarySearch(items, new Item(5, ""), itemNumComparator);
Item removedItem = null;
// binarySearch will return -1 if it does not find the element.
if (index > -1) {
// This will remove the element, Item(5, "cow") in this case, from the list
removedItem = items.remove(index);
}
System.out.println(removedItem);
}
To search for another field like name, for example, you would need to create a name comparator and use it to sort and run the binary search on your list.
Note this solution has some drawbacks though. Unless you are completely sure that the list didn't change since the last sort, you must re-sort it before running the binarySearch() method. Otherwise, it may not be able to find the correct element. Sorting complexity is O(nlogn), so running it multiple times can get quite expensive depending on the size of your list.
Do you want to remove an object at a specific index? I'm not entirely sure what you mean by 'number field'. If so, jump to method: remove(int):
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#remove%28int%29
EDIT: If you want to find/adjust a field of an object in the Array list, you can do this (piece of my own code):
public boolean studentHasISBN(ArrayList<Student> st, String s){
for(Student j : st) {
if(s.equals(j.getRentedBookISBN()))
return true;
}
return false;
}
All you have to do is iterate through the list, and search through the field that you want to find. Then use the remove(int) method.
simply use the remove function of ArrayLists in Java:
theNameOfYourArrayList.remove(ItemNumber);
to remove the element which has the index (int ItemNumber)
to check if the element with item number (int ItemNumber) exists in your ArrayList (hypothetically called theNameOfYourArrayList):
theNameOfYourArrayList.get(ItemNumber);
I'm going to assume that by 'number field' you mean that you invoked ArrayList with the Integer data type. I have a few different solutions to your problem:
ArrayLists, assuming that the ArrayList is ArrayList<Integer> numList = new ArrayList<Integer>(); you can simply write a method that will search 'numList' and delete the index that the number is. The problem is, contains and find in ArrayLists can be slow.
public void deleteNumField(int field) {
// this will stop any error if field isn't actually in numList
// and it will remove the first index of field in the ArrayList
if(numList.contains(field)) numList.remove(numList.find(field));
}
HashSets, HashSets are a handy data type that is like an ArrayList, except, its data is its 'index' (sortof). I won't go in depth about how they work, but I will say that searching in them is considered O(1). This will make your deletion really easy, and fast. Note: the HashSet assumes there are no duplicate numbers, if there are use a HashMap.
HashSet<Integer> numList = new HashSet<Integer>();
public void deleteNumField(int field) {
// this will stop errors from attempting to remove a
// non-existant element, and remove it if it exists.
if(numList.contains(field)) numList.remove(field);
}
For more information on HashMaps, HashSets and ArrayLists, see:
http://docs.oracle.com/javase/8/docs/api/
I have a list of objects, and inside these objects I have another list. I would like to know if there's a simple way to load a list of those lists inside the object. I want to choose a parameter from the object (userCode for example), and I want that list to return all the lists from all the objects with the matching userCode.
If anyone could help me, I'll be forever grateful.
Thank you
Well the most straight forward way of iterating should be fine here. Just loop through the list and get the lists from the objects and add them to another list. below is a sample template.
List<List<T>> listOfLists = new ArrayList<>();
for (Obj o : listOfObjects){
listOfLists.add(o.list);
}
Let assume you have populated a list of lists somewhere like this:
List<List<Object>> list1 = new ArrayList<List<Object>>();
for(List<Object> list : list1){
List<Object> list2 = new ArrayList<Object>();
list.add(list2);
}
Then you could create something like this to find your object:
List<List<Object>> find = new ArrayList<List<Object>>();
for(List<Object> list : list1){
for(int i=0;i<list.size();i++){
if(list.get(i).toString().equals("userCode")){
find.add(list);
break;
}
}
}
return find;
Note that I assumed an Object you should put your condition in the if statment.
Start with some object that has a userCode and list fields:
class X {
private int userCode;
private List<Y> list;
int getUserCode(){ return userCode; }
List<Y> getList() { return list; }
}
and assume we've got a list of these guys:
List<X> listOfX;
What you want is covert each X in the list to an entry in a map. Here's a simple function that converts of list of X's to a Map
Map<Integer, List<Y>> buildMap(List<X> list) {
Map<Integer, List<Y>> map = new HashMap<Integer, ArrayList<Y>>();
for(X x:list) {
map.put(x.getUserCode(), x.getList());
}
return map;
}
The keys in the map are the userCode's from your list of X's and the values are X's list fields:
List<Y> listOfY = map.get(someUserCode);
I have an arrayList of arrayLists. Each inner arraylist contains some objects with the format (name.version) .
{ {a.1,b.2,c.3} , {a.2,d.1,e.1} , {b.3,f.1,z.1}....}
For example a.1 implies name = a and version is 1.
So i want to eliminate duplicates in this arraylist of lists. For me , two objects are duplicate when they have the same name
So essentially my output should be
{ { a.1,b.2,c.3},{d.1,e.1} ,{f.1 ,z.1} }
Note that i want the output in the exact same form (That is , i dont want a single list with no duplicates)
Can someone provide me with an optimal solution for this?
I can loop through each inner list and place the contents in the hashset. But two issues there, i cant get back the answer in
form of list of lists.Another issue is that when i need to override equals for that object , but i am not sure if that would
break other code. These objects are meaningfully equal if their names are same (only in this case. I am not sure that would
cover the entire spectrum)
Thanks
I used Iterator.remove() to modify the collection as you move through it.
// build your example input as ArrayList<ArrayList<String>>
String[][] tmp = { { "a.1", "b.2", "c.3" }, { "a.2", "d.1", "e.1" },
{ "b.3", "f.1", "z.1" } };
List<List<String>> test = new ArrayList<List<String>>();
for (String[] array : tmp) {
test.add(new ArrayList<String>(Arrays.asList(array)));
}
// keep track of elements we've already seen
Set<String> nameCache = new HashSet<String>();
// iterate and remove if seen before
for (List<String> list : test) {
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String element = it.next();
String name = element.split("\\.")[0];
if (nameCache.contains(name)) {
it.remove();
} else {
nameCache.add(name);
}
}
}
System.out.println(test);
Output
[[a.1, b.2, c.3], [d.1, e.1], [f.1, z.1]]
List<List<Pair>> inputs; // in whatever format you have them
List<List<Pair>> uniqued = new ArrayList<>(); // output to here
Set<String> seen = new HashSet<String>();
for (List<Pair> list : inputs) {
List<Pair> output = new ArrayList<>();
for (Pair p : list)
if (seen.add(p.getName()))
output.add(p);
uniqued.add(output);
}
Create a Set. Iterate over the list of lists' items. See if the item is in the Set. If it is already there, ignore it. If it isn't, add it to the Set and the list of lists.
Your method will return a new list of lists, not modify the old one. Modifying a list while iterating over it is a pain.
I have an ArrayList that I want to iterate over. While iterating over it I have to remove elements at the same time. Obviously this throws a java.util.ConcurrentModificationException.
What is the best practice to handle this problem? Should I clone the list first?
I remove the elements not in the loop itself but another part of the code.
My code looks like this:
public class Test() {
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff() {
for (A a : abc)
a.doSomething();
}
public void removeA(A a) {
abc.remove(a);
}
}
a.doSomething might call Test.removeA();
Two options:
Create a list of values you wish to remove, adding to that list within the loop, then call originalList.removeAll(valuesToRemove) at the end
Use the remove() method on the iterator itself. Note that this means you can't use the enhanced for loop.
As an example of the second option, removing any strings with a length greater than 5 from a list:
List<String> list = new ArrayList<String>();
...
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String value = iterator.next();
if (value.length() > 5) {
iterator.remove();
}
}
From the JavaDocs of the ArrayList
The iterators returned by this class's iterator and listIterator
methods are 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.
You are trying to remove value from list in advanced "for loop", which is not possible, even if you apply any trick (which you did in your code).
Better way is to code iterator level as other advised here.
I wonder how people have not suggested traditional for loop approach.
for( int i = 0; i < lStringList.size(); i++ )
{
String lValue = lStringList.get( i );
if(lValue.equals("_Not_Required"))
{
lStringList.remove(lValue);
i--;
}
}
This works as well.
In Java 8 you can use the Collection Interface and do this by calling the removeIf method:
yourList.removeIf((A a) -> a.value == 2);
More information can be found here
You should really just iterate back the array in the traditional way
Every time you remove an element from the list, the elements after will be push forward. As long as you don't change elements other than the iterating one, the following code should work.
public class Test(){
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff(){
for(int i = (abc.size() - 1); i >= 0; i--)
abc.get(i).doSomething();
}
public void removeA(A a){
abc.remove(a);
}
}
While iterating the list, if you want to remove the element is possible. Let see below my examples,
ArrayList<String> names = new ArrayList<String>();
names.add("abc");
names.add("def");
names.add("ghi");
names.add("xyz");
I have the above names of Array list. And i want to remove the "def" name from the above list,
for(String name : names){
if(name.equals("def")){
names.remove("def");
}
}
The above code throws the ConcurrentModificationException exception because you are modifying the list while iterating.
So, to remove the "def" name from Arraylist by doing this way,
Iterator<String> itr = names.iterator();
while(itr.hasNext()){
String name = itr.next();
if(name.equals("def")){
itr.remove();
}
}
The above code, through iterator we can remove the "def" name from the Arraylist and try to print the array, you would be see the below output.
Output : [abc, ghi, xyz]
Do the loop in the normal way, the java.util.ConcurrentModificationException is an error related to the elements that are accessed.
So try:
for(int i = 0; i < list.size(); i++){
lista.get(i).action();
}
Here is an example where I use a different list to add the objects for removal, then afterwards I use stream.foreach to remove elements from original list :
private ObservableList<CustomerTableEntry> customersTableViewItems = FXCollections.observableArrayList();
...
private void removeOutdatedRowsElementsFromCustomerView()
{
ObjectProperty<TimeStamp> currentTimestamp = new SimpleObjectProperty<>(TimeStamp.getCurrentTime());
long diff;
long diffSeconds;
List<Object> objectsToRemove = new ArrayList<>();
for(CustomerTableEntry item: customersTableViewItems) {
diff = currentTimestamp.getValue().getTime() - item.timestamp.getValue().getTime();
diffSeconds = diff / 1000 % 60;
if(diffSeconds > 10) {
// Element has been idle for too long, meaning no communication, hence remove it
System.out.printf("- Idle element [%s] - will be removed\n", item.getUserName());
objectsToRemove.add(item);
}
}
objectsToRemove.stream().forEach(o -> customersTableViewItems.remove(o));
}
One option is to modify the removeA method to this -
public void removeA(A a,Iterator<A> iterator) {
iterator.remove(a);
}
But this would mean your doSomething() should be able to pass the iterator to the remove method. Not a very good idea.
Can you do this in two step approach :
In the first loop when you iterate over the list , instead of removing the selected elements , mark them as to be deleted. For this , you may simply copy these elements ( shallow copy ) into another List.
Then , once your iteration is done , simply do a removeAll from the first list all elements in the second list.
In my case, the accepted answer is not working, It stops Exception but it causes some inconsistency in my List. The following solution is perfectly working for me.
List<String> list = new ArrayList<>();
List<String> itemsToRemove = new ArrayList<>();
for (String value: list) {
if (value.length() > 5) { // your condition
itemsToRemove.add(value);
}
}
list.removeAll(itemsToRemove);
In this code, I have added the items to remove, in another list and then used list.removeAll method to remove all required items.
Instead of using For each loop, use normal for loop. for example,the below code removes all the element in the array list without giving java.util.ConcurrentModificationException. You can modify the condition in the loop according to your use case.
for(int i=0; i<abc.size(); i++) {
e.remove(i);
}
Sometimes old school is best. Just go for a simple for loop but make sure you start at the end of the list otherwise as you remove items you will get out of sync with your index.
List<String> list = new ArrayList<>();
for (int i = list.size() - 1; i >= 0; i--) {
if ("removeMe".equals(list.get(i))) {
list.remove(i);
}
}
You can also use CopyOnWriteArrayList instead of an ArrayList. This is the latest recommended approach by from JDK 1.5 onwards.
Do somehting simple like this:
for (Object object: (ArrayList<String>) list.clone()) {
list.remove(object);
}
An alternative Java 8 solution using stream:
theList = theList.stream()
.filter(element -> !shouldBeRemoved(element))
.collect(Collectors.toList());
In Java 7 you can use Guava instead:
theList = FluentIterable.from(theList)
.filter(new Predicate<String>() {
#Override
public boolean apply(String element) {
return !shouldBeRemoved(element);
}
})
.toImmutableList();
Note, that the Guava example results in an immutable list which may or may not be what you want.
for (A a : new ArrayList<>(abc)) {
a.doSomething();
abc.remove(a);
}
"Should I clone the list first?"
That will be the easiest solution, remove from the clone, and copy the clone back after removal.
An example from my rummikub game:
SuppressWarnings("unchecked")
public void removeStones() {
ArrayList<Stone> clone = (ArrayList<Stone>) stones.clone();
// remove the stones moved to the table
for (Stone stone : stones) {
if (stone.isOnTable()) {
clone.remove(stone);
}
}
stones = (ArrayList<Stone>) clone.clone();
sortStones();
}
I arrive late I know but I answer this because I think this solution is simple and elegant:
List<String> listFixed = new ArrayList<String>();
List<String> dynamicList = new ArrayList<String>();
public void fillingList() {
listFixed.add("Andrea");
listFixed.add("Susana");
listFixed.add("Oscar");
listFixed.add("Valeria");
listFixed.add("Kathy");
listFixed.add("Laura");
listFixed.add("Ana");
listFixed.add("Becker");
listFixed.add("Abraham");
dynamicList.addAll(listFixed);
}
public void updatingListFixed() {
for (String newList : dynamicList) {
if (!listFixed.contains(newList)) {
listFixed.add(newList);
}
}
//this is for add elements if you want eraser also
String removeRegister="";
for (String fixedList : listFixed) {
if (!dynamicList.contains(fixedList)) {
removeResgister = fixedList;
}
}
fixedList.remove(removeRegister);
}
All this is for updating from one list to other and you can make all from just one list
and in method updating you check both list and can eraser or add elements betwen list.
This means both list always it same size
Use Iterator instead of Array List
Have a set be converted to iterator with type match
And move to the next element and remove
Iterator<Insured> itr = insuredSet.iterator();
while (itr.hasNext()) {
itr.next();
itr.remove();
}
Moving to the next is important here as it should take the index to remove element.
List<String> list1 = new ArrayList<>();
list1.addAll(OriginalList);
List<String> list2 = new ArrayList<>();
list2.addAll(OriginalList);
This is also an option.
If your goal is to remove all elements from the list, you can iterate over each item, and then call:
list.clear()
What about of
import java.util.Collections;
List<A> abc = Collections.synchronizedList(new ArrayList<>());
ERROR
There was a mistake when I added to the same list from where I took elements:
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
for (i in this) {
this.add(_fun(i)) <--- ERROR
}
return this <--- ERROR
}
DECISION
Works great when adding to a new list:
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
val newList = mutableListOf<T>() <--- DECISION
for (i in this) {
newList.add(_fun(i)) <--- DECISION
}
return newList <--- DECISION
}
Just add a break after your ArrayList.remove(A) statement
I have two questions. I have an object here that is of type ArrayList, and for this case let's call it "Car".
I have made 2 of them:
Car car1 = new Car();
Car car2 = new Car();
I have a function to add items to those Car objects:
car1.addPart("Front Wheels");
car1.addPart("Rear Wheels");
car1.addPart("Rear View Mirror");
car2.addPart("Rims");
car2.addPart("Steering Wheel");
car2.addPart("Bumper");
I need to have a function called sameContents() that I can call on car1:
car1.sameContents(car2);
which passes in an object of type ArrayList and checks it with car1 to see if they have the same contents and in the same order.
public boolean sameContents(Car c) {
ArrayList<String> other_car = c; // error: Type mismatch:
// cannot convert from Car to ArrayList<String>
for (String c : this.parts) {
System.out.println(c);
for(String oc : other_car) {
// stuff
}
}
}
I seem to be having all sorts of issues with this one. I can't get the other_car variable to be used in a foreach loop.
The second one that needs to be done is transferContents.
It's called like:
car1.transferContents(car2);
which transfers the items in car2 into car1 and then leaves car2 empty. I can't seem to get the ArrayList to work again in a foreach loop which is what I think I need.
public void transfer(Car c) {
// code for transfer method.
// this.parts is the arraylist of car parts
for (Car c: c) {
this.parts.add(c);
}
// not sure how to set car2 to empty...
}
Given some List<T> foo, foreach loops, e.g.:
for(T item : foo){
// body
}
are just a shorthand syntax for this idiom:
Iterator<T> iter = foo.iterator();
while(iter.hasNext()){
T item = iter.next();
// body
}
To check that there are more items in the list, you call iter.hasNext(), to retrieve the next item, you call iter.next().
Walking two lists can be done by keeping around 2 iterators, checking that both iterators have more elements, and then retrieving those elements. We can eliminate some boundary conditions on different length lists by realizing that different length lists cannot contain the same elements (since one list has more than the other).
From your description, it sounds like Car contains a property List<String> parts;, so we can formulate a solution as:
// different sizes, can't be equal
if(this.parts.size() != other.parts.size()){
return false;
}
// get iterators
Iterator<String> left = this.parts.iterator();
Iterator<String> right = other.parts.iterator();
// safe to only check `left` because the lists are the same size
while(left.hasNext()){
// check if left part is equal to the right part
if(!left.next().equals(right.next())){
// values are different, know at this
// point they're not equal
return false;
}
}
// at this point, have exactly the same values
// in the same order.
return true;
As for your transferContents method, you have the right idea, but you cannot iterate over the Car, you need to iterate over the List<String> parts. To remove individual parts, you can use remove() method, called like the add method, or to remove all elements, you can call clear()
Putting this together:
for (String part : c.parts) {
this.parts.add(part);
}
c.parts.clear();
You can rely on the java api to do all that you need.
The ArrayList equals method checks for order while comparing two lists.
You can use the removeAll() and addAll() methods to transfer contents.
public class Car {
private final List<String> parts = new ArrayList<String>();
public void addPart(String p) {
parts.add(p);
}
public boolean sameContents(Car c) {
return this.parts.equals(c.parts);
}
public void transfer(Car c) {
final List<String> temp = new ArrayList<String>(c.parts);
temp.removeAll(this.parts);
this.parts.addAll(temp);
c.parts.clear();
}
}
Your car should not be an array list, but have one. E.g. something like this:
class Car {
ArrayList<String> parts;
// ...
}
Then your sameContents method can simply call the lists's .equals() method to do the comparison:
public boolean sameParts(Car other) {
return this.parts.equals(other.parts);
}
Similarly, for transferring parts from another car, use the methods of the Lists to add the parts to your list, and then clear the other list.