Issue iterating through ArrayLists - java

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.

Related

How to output list of names in an object? Java

I have a function that I want to output a list of all the names in the object. What is the easiest way to do this?
Requirement object has a names variable and a method called getChildren which contains a list of Requirements.
Void updateItems(Requirement r)
{
System.out.println(r.getChildren.names) //doesnt work
}
I want to output all the names of the children objects like this:
Hello1, Hello2, Hello3
Requirement object has a names variable and a method called
getChildren which contains a list of Requirements.
the code below will retrieve the children's list for the current r object and iterate over its list in order to display their names.
void updateItems(Requirement r)
{
r.getChildren().forEach(c -> System.out.print(c.names+" "));
}
You mentioned "getChildren contains a list of Requirements". I guess you mean getChildren returns a list of Requirement objects?
If that's right. You could try:
void updateItems(Requirement r) {
for (Requirement child: r.getChildren()) {
System.out.println(child.names);
}
}
You said the method getChildren contains a list.
So you must iterate through the elements of the list to get the output:
First: Create a variable for your list.
ArrayList<String> x = new ArrayList<>();
Then you can call the getChildren method to save your list:
x = getChildren();
And then you can iterate through it.
for(String names : x){
System.out.println(names);
}
That means:
void updateItems(Requirement r)
{
ArrayList<String> x = new ArrayList<>();
x = r.getChildren();
for(String names : x){
System.out.println(names);
}
}

How do you add elements from one ArrayList to another?

So I have one ArrayList of fruits which has the name of the fruit and what its predominant vitamin is:
ArrayList<Foods> fruit;
public Fruit() {
fruit = new ArrayList<Foods>();
fruit.add(new Foods("Orange", "Vitamin C"));
}
etc..
I want to add all the fruits with vitamin C to another array list so I iterated over them using:
Iterator vitC = fruit.iterator();
while (vitC.hasNext()) {
if (vitC.next().contains("Vitamin C")) {
vitCfruit.add(vitC.next());
}
}
However this adds the next value, so if apple was after orange in the list it would add apple to the next ArrayList instead of orange.
I'll ignore the apparent error in the code. In order to work with the element on the list you should do the following:
Iterator vitC = fruit.iterator();
while (vitC.hasNext()) {
Foods x = vitC.next();
if (x.contains("Vitamin C")) { // should look for a Foods object here!!!
administrators.add(x);
}
}
the vitC.next() in the 'if' you declared will work, but you will not be accessing the same element in the next line when add it to the new list.
use a tmp variable to store the vitC.next() and in case it match the condition you can still add ot..
Iterator vitC = fruit.iterator();
while (vitC.hasNext()) {
tmp = vitC.next();
if (tmp.contains("Vitamin C")) { // should look for a Foods object here!!!
administrators.add(tmp);
}
}
The enhanced for loop makes this straightforward:
for (Fruit thisFruit : fruit) {
if (thisFruit.contains("Vitamin C")) {
vitCfruit.add(thisFruit);
}
}
In Java 8, this is simple with lambdas:
List<Foods> vitCfruit = fruit.stream()
.filter(f -> f.contains("Vitamin C"))
.collect(Collectors.toList());

Remove an object from an ArrayList given only one attribute

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/

Removing common elements between two different Arraylist

I have read several posts for this but not getting the exact thing I am looking for. I know how to develop a complex logic for this, this is for Android and we can't expect too much processing on the device due to the limited resources available.
I have an ArrayList of an bean class objects consisting five fields as
Java Bean -- MyShares
fileName
filePath
fileSize
isShared
Creator
I have another ArrayList of String which contains only filepaths. Now what I want is to remove all the common elements between the two arraylist means the file paths in seconds arraylist and file path in first arraylist objects are similar then I have to remove from both of the arraylist but I don't want a new arraylist which contains the uncommon elements. But I want to get my both arraylist only without their common elements.
You could use a Map from String to your object type (I used Obj in order to make a SSCCE).
Assume we are given a list objects and a list strings.
Steps:
Put all objects in a map with their str variable as key
Get all those str variables using map.keySet()
Get all strings that are in objects but not in strings by keys.removeAll(strings)
Get all strings that are in strings but not in objects by strings.removeAll(keys)
Get the objects that correspond to the remaining keys
Note that you need to be careful in steps 3 and 4, because you need to back up one of the collections.
import java.util.*;
public class Test {
public static void main(String[] args) throws Exception {
new Test();
}
public Test() {
List<Obj> objects = new ArrayList<>();
objects.add(new Obj("a"));
objects.add(new Obj("b"));
objects.add(new Obj("c"));
List<String> strings = new ArrayList<>();
strings.add("a");
strings.add("d");
strings.add("e");
remove(objects, strings);
System.out.println(objects);
System.out.println(strings);
}
public void remove(List<Obj> objects, List<String> strings) {
Map<String, Obj> map = new HashMap<>();
for (Obj object : objects) {
map.put(object.str, object);
}
Set<String> keys = map.keySet();
List<String> oldStrings = new ArrayList<>(strings);
strings.removeAll(keys);
keys.removeAll(oldStrings);
objects.clear();
for (String key: keys) {
objects.add(map.get(key));
}
}
public class Obj {
public String str;
public Obj(String str) {
this.str = str;
}
#Override
public String toString() {
return str;
}
}
}
Prints:
[b, c]
[d, e]
Rough Java code:
HashSet<String> commonKeys = new HashSet();
for (Share share : shares) {
commonKeys.add(share.filePath);
}
commonKeys.retainAll(filePaths);
for (Iterator<Share> it = shares.iterator(); it.hasNext(); ) {
Share share = it.next();
if (commonKeys.contains(share.filePath)) {
it.remove();
}
}
filePaths.removeAll(commonKeys);
This won't be O(N) because remove on an ArrayList is expensive. To get O(N) behavior you either need to create new ArrayList instances, or add the elements you don't want removed to temporary lists, and then clear() and add them back into the original lists.
I will go with some clues for you
Suppose you have two lists one for bean objects namely myBeans and another for filePaths namely filePaths
List<MyBean> beansToRemove = new ArrayList<MyBean>();
List<FilePath> filePathsToRemove = new ArrayList<FilePath>();
for(Bean myBean : myBeans) {
for(FilePath filePath : filePaths) {
if(myBean.getfilePath.equals(filePath.getFilePath())) {
beansToRemove.add(myBean);
filePathsToRemove.add(filePath);
}
}
}
//Now remove filePaths and beans if any
for(Bean myBean : beansToRemove) {
myBeans.remove(myBean);
}
for(FilePath filePath : filePathsToRemove) {
filePaths.remove(filePath);
}
it is just a flow to make you clear for what to do; you can further customize it according to your needs.
You can use an outer loop to scan over the Bean objects, and an inner loop to scan over the file paths.
pseudo code:
for (Bean i in beans) {
for (String p in paths) {
if (i.path.equals(p)) {
beansToRemove.add(i);
pathsToRemove.add(p);
}
}
}
beans.removeAll(beansToRemove);
paths.removeAll(pathsToRemove);
I'm not sure if my extra arraylists to track the removed arraylists go against your question or not since the original arrays remain.
If you presort both arrays on the path and keep track of the position in each area (not exhaustive search) you can improve it from n2 to nlgn

Iterating and processing an ArrayList

I have a List of objects. I want to iterate through this list of objects and process some subsets of objects based on a condition and finally create a new list of objects with some processed objects being eliminated.
What is the best way to do this.?
Example:
Actual object : List<Cars>
Iterate through this list and find Cars with same speed.
In that smaller set of Cars, the ones which are of same model are to be eliminated.
Finally after elimination I get the new list.
The Google Guava libraries have:
Iterables.filter(cars, new Predicate<Car>() {
#Override
public boolean apply(Car car) {
//return true or false depending on whether you
// want this car to remain in the list
}
}
You can also use an intermediate Set - i.e.
cars = new ArrayList<Car>(new HashSet<Car>(cars));
where you have properly implemented hashCode and equals. This option is viable if this is the identity of your car.
You can also use an iterator:
for (Iterator<Car> it = cars.iterator(); it.hasNext();) {
Car car = it.next();
if (conditions here) {
it.remove();
}
}
By the way, I'm aware that the above examples don't solve your problem completely - you should still consider what to iterate within the outer loops.
If you are looking to do custom equals comparing, then you should define a Comparator<Car> and then just loop through the Cars.
List<Car> originalList;
Comparator<Car> c = new CarSpeedComparator();
List<Car> result = carFilter(originalList, c);
/// Below is the filter method
public static List<Car> carFilter(List<Car> original, Comparator<Car> comp)
List<Car> result = new ArrayList<Car>();
// Process each car
for (Car car: original) {
boolean containsC = false;
// now we check each car in the result
// to see if we already have an equivalent car
for (int i = 0; i < result.size(); i++) {
// if the two cars are equivalent under the rules
// then we already have that car in the list
if (comp.compare(result.get(i), car) == 0) {
containsC = true;
break;
}
}
// if the result does not contain an equivalent car,
// add it to the list
if (!containsC) result.add(car)
}
return result;
}
//// Implementation of one of the necessary comparators
public class CarSpeedComparator implements Comparator<Car> {
public int compare(Car c1, Car c2) {
return c1.getSpeed() - c2.getSpeed();
}
}
The resulting list will only contain one car of each speed.
It sounds like what you might want to do first is index the cars in your list by speed. Once you've done that, it might be easier to do the rest of the processing you're looking for. Guava's Multimaps are good for this:
ImmutableListMultimap<Integer, Car> speedIndex = Multimaps.index(cars,
new Function<Car, Integer>() {
public Integer apply(Car from) {
return from.getSpeed();
}
});
Now speedIndex will be a multimap that lets you do something like this:
for (Integer speed : speedIndex.keySet()) {
ImmutableList<Car> carsWithSpeed = speedIndex.get(speed);
// Do stuff
}
This gives you groupings of all cars in the original list that have the same speed. You could then do whatever processing on them you wanted. You might want to index this group of cars by model, giving you groupings of cars that have both the same speed and model. You could then remove those cars from the original list if you wanted. Alternatively, if you don't want to modify the original list at all but just get a copy of the list with a set of cars removed, you could add each car to be removed to a Set, then get the copy with those cars removed like this:
Set<Car> carsToRemove = ...;
List<Car> filteredList = Lists.newArrayList(Iterables.filter(cars,
Predicates.not(Predicates.in(carsToRemove))));
If you did this repeatedly on big lists, you'd want to be more efficient. Keep a list of objects, but also keep separate lists for each model of car; Hashtable<String, List> models. That way, you already have the model part done for future sorts. It takes slightly more memory, but notably less time to search through.
To me it looks like the OP just wants a unique set of (model,speed) pair. If so, here is a easy way to do it:
class Car {
private final String model;
private final int speed;
public int hashCode(){
return model.hashCode() + speed;
}
public boolean equals(Object obj){
//check on null/different class omitted.
Car other = (Car)obj;
return this.model.equals(obj.model) && this.speed == other.speed;
}
}
then
Set<Car> cars = new HashSet<Car>(originalListOfCars);

Categories