Move element from one array list to another java - java

i have a problem
I have two lists
List<SellableItems> table1 = new ArrayList();
List<SellableItems> table2 = new Arraylist();
In my sellable items class, i have a name and a price.
Now I wish to move elements from table1 to table2. So if i my list contains a beer with the price 20, i can move it from table1 to table2

Iterate over the source list, if an item matches your criteria remove it from the source list and add it to the target list :
for(int i=0; i<table1.size(); i++) {
if(table1.get(i).price==20) {
table2.add(table1.remove(i));
}
}
Or with a foreach loop :
for(SellableItem item : table1) {
if(item.price==20) {
table1.remove(item);
table2.add(item);
}
}

If you want to move a specific item :
moveSellableItem(List<SellableItem> source, SellableItem item, List<SellableItem> destination){
destination.add(item);
source.remove(item);
}
If you want to move all item with a specific parameter (price in example) :
moveSellableItemWithPrice(List<SellableItem> source, double price, List<SellableItem> destination)
{
var itemsToMove = new ArrayList<SellableItem>();
for(SellableItem item : source){
if(item.price == price) {
itemsToMove.add(item);
}
}
source.removeAll(itemsToMove);
destination.addAll(itemsToMove);
}
In addition, you can use a lambda instead of the foreach loop :
From Java 8 :
var itemsToMove = source.stream().filter(i -> i.price == price).collect(Collectors.toList());
From Java 16 :
var itemsToMove = source.stream().filter(i -> i.price == price).toList();

import java.util.List;
import java.util.ArrayList;
public class Details
{
public static void main(String [] args)
{
//First ArrayList
List<SellableItems> arraylist1=new ArrayList<SellableItems>();
arraylist1.add(SellableItems);
//Second ArrayList
List<SellableItems> arraylist2=new ArrayList<SellableItems>();
arraylist2.add(SellableItems);
arraylist1.addAll(arraylist2);
}
}
this can be done see this example
you can refer to the begginers book for the collection framework

Iterate on the first list and add to the second list when price equals 20:
List<SellableItems> table1 = new ArrayList<>();
List<SellableItems> table2 = new ArrayList<>();
Iterator<SellableItems> itemsIterator = table1.iterator();
while (itemsIterator.hasNext()) {
SellableItems next = itemsIterator.next();
if (next.price.equals(20)) {
table2.add(next);
itemsIterator.remove();
}
}

Perhaps use a stream to add all the values where name = beer and price = 20
table1.stream().filter((table11) -> (table11.getName().equals("beer") && table11.getPrice() == 20)).forEach((table11) -> {
table2.add(table11);
});
Then remove all from the original list (if required)
table1.removeAll(table2);

I assume that you want to filter the first list and store the result into another list so that you have the original and a modified version of the same list.
Since I do not know how your SellableItem class is structured I used some Integers for my example:
// List of random Integers for the example
List<Integer> li = new Random().ints( 100,0,30 ).boxed().collect( Collectors.toList() );
// The list which will contain the results
List<Integer> target;
// A stream (since Java 8) which is filtering for a certain Predicate and
// collecting the result as a list.
target = li.stream().filter( i->i.intValue() > 20 ).collect( Collectors.toList() );
System.out.println( target );
In this case target will only contain items which are applicable to their value being bigger than 20.
However if you don't want to keep the original and remove the items you stored in the 2nd list you can call li.removeAll(target);.

Here are two additional options:
Iterator<SellableItem> iter = table1.iterator();
while (iter.hasNext()) {
SellableItem item = iter.next();
if (item.getName().equals("beer") && item.getPrice() == 20) {
iter.remove();
table2.add(item);
}
}
and
Predicate<SellableItem> test = item -> item.getName().equals("beer") && item.getPrice() == 20;
table1.stream().filter(test).forEach(table2::add);
table1.removeIf(test);

Related

Using an Iterator inside a for loop to remove elements from an ArrayList

I have an ArrayList of objects that have a version number as a field. I want to do some work on that ArrayList, but I only want the most recent version of the object. I was thinking of coding as such:
ArrayList<ObjectVO> ObjectList = getObjectList();
for(ObjectVO myVO : ObjectList) {
Iterator<ObjectVO> iter = ObjectList.iterator();
while(iter.hasNext()) {
ObjectVO checkVO = iter.next();
if(myVO.getID().equals(checkVO.getID()) {
//they are the same object ID. Check the version number, remove it lower
if(myVO.getVersion() > checkVO.getVersion()) {
iter.remove();
}
}
}
}
Is this valid? I don't know if the fact that we are in a for loop originally would break the mutability of the ArrayList at runtime.
No, this won't work. iter.remove() will cause the out for loop to fail with ConcurrentModificationException.
Instead of doing this, you can do this with indexed for loops, and a BitSet to keep track of things you want to remove:
BitSet toRemove = new BitSet();
for (int m = 0; m < ObjectList.size(); ++m) {
if (toRemove.get(m)) continue;
ObjectVO myVO = ObjectList.get(m);
for (int c = 0; c < ObjectList.size(); ++c) {
if (toRemove.get(c)) continue;
ObjectVO checkVO = ObjectList.get(c);
if(myVO.getID().equals(checkVO.getID()) {
//they are the same object ID. Check the version number, remove it lower
if(myVO.getVersion() > checkVO.getVersion()) {
toRemove.set(c);
}
}
}
}
This is basically your code, but it doesn't do the removal yet. Then you can sweep through the list after and remove them:
int dst = 0;
for (int src = 0; src < ObjectList.size(); ++src) {
if (!toRemove.get(src)) {
ObjectList.set(dst++, ObjectList.get(src));
}
}
ObjectList.subList(dst, ObjectList.size()).clear();
The point of using a BitSet like this is that removal from an ArrayList is inefficient if you are removing from anywhere other than the end, because it requires all of the elements "to the right" of the element you remove to be shuffled along by one position. The loop with the set/get and clear allows you to only move each of the retained elements once.
You can do a bit better than the quadratic loop, though, if you group the list elements by things with the same ID: then you don't need to keep on checking the entire list:
BitSet toKeep = new BitSet();
IntStream.range(0, ObjectList.size())
.mapToObj(a -> a)
.collect(
groupingBy(a -> ObjectList.get(a).getID(),
maxBy(comparingInt(a -> ObjectList.get(a).getVersion()))))
.values()
.forEach(a -> toKeep.set(a));
int dst = 0;
for (int src = 0; src < ObjectList.size(); ++src) {
if (toKeep.get(src)) {
ObjectList.set(dst++, ObjectList.get(src));
}
}
ObjectList.subList(dst, ObjectList.size()).clear();
Assuming you have the memory, rather than do an O(N^2) operation, you could do this more efficiently (O(N)) by using a Map to track the newest Version for each Id. One pass tracks the newest version for each Id, and the second removes elements which are not the latest.
Map<Integer, Thing> newestById = new HashMap<>();
for (Thing thing : list) {
newestById.merge(thing.id, thing, (a,b) -> a.version > b.version ? a : b);
}
list.removeIf(thing -> thing != newestById.get(thing.id)); }
Depending on your use case, you might even be able to store your data in a Map instead of a List, and check if the version is the latest before adding it to the Map.
As the other answers have discussed this won't work. You have three options as I see them, trading memory for CPU cycles/flexibility. I've used Integer instead of ObjectVO in my examples, but it'll be trivial to swap them.
Option 1 - moderate memory, single-pass of the array
Track the highest ID you've seen and populate an ArrayList with new items as they meet the criteria. When you encounter a new higher ID, throw away the ArrayList and create a new one:
ArrayList<Integer> objectList = getObjectList();
Integer bestId = -1;
ArrayList<Integer> allObjectsMatchingId = new ArrayList<>();
for(Integer currentObject : objectList) {
if(currentObject > bestId) {
bestId = currentObject;
allObjectsMatchingId = new ArrayList<>();
} else if(currentObject == bestId) {
allObjectsMatchingId.add(currentObject);
}
}
return allObjectsMatchingId;
Option 2 - more expensive memory, single-pass of the array, most flexible.
For each ID you see, create an ArrayList and store it against a map. This allows you to easily change the criteria about what ID you want to keep.
ArrayList<Integer> objectList = getObjectList();
Map<Integer, ArrayList<Integer>> objectsById = new HashMap<>();
for(Integer currentObject : objectList) {
ArrayList<Integer> listForId = objectsById.get(currentObject);
if(listForId == null) {
listForId = new ArrayList<Integer>();
}
listForId.add(currentObject);
objectsById.put(currentObject, listForId);
}
Integer bestId = -1;
for(Integer i : objectsById.keySet()) {
if(i > bestId) {
bestId = i;
}
}
return objectsById.get(bestId);
Option 3 - no additional memory aside from id, two-passes of the array.
Search through the ArrayList for the highest ID, then filter the array to only elements that pass that filter.
This is the closest to your current implementation, the difference being that you do them in separate steps. This reduces complexity from O(N^2) to O(N), and is valid as you aren't modifying the ArrayList while iterating it. You could use a Stream here to filter instead of an iterator if you're Java 8 compatible. See Java: Efficient ArrayList filtering?
ArrayList<Integer> objectList = getObjectList();
Integer bestId = -1;
for(Integer currentObject : objectList) {
if(currentObject > bestId) {
bestId = currentObject;
}
}
Iterator<Integer> iter = objectList.iterator();
while(iter.hasNext()) {
if(iter.next() != bestId) {
iter.remove();
}
}
Why not use Java Streams to solve this:
Collection<ObjectVO> result = objectList.stream()
.collect(Collectors.toMap(ObjectVO::getID, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(ObjectVO::getVersion))))
.values();
This creates a map which contains the max version for each id. Then you can just use Map.values() to get the object list.
If you need a List or an ArrayList you can just use new ArrayList<>(result).

How to compare elements inside List of strings with Array List of string?

I have added products to my basket and listed their URL in a List and want to verify these products against given String[] of products
the items are stored backwards in z String[] so the last item here is the 1st item in the List .. the number of items is 3 and below code works for 2 items and throw invoker exception at the assert method in the third item
public void verifyBag(String[] goods) {
actions.clickOn(By.xpath(bagLocator));
Arrays.sort(goods);
List<WebElement> listItems = actions.driver.findElements(By.xpath(bagItems));
List <String> actualItems = new ArrayList<String>();
for(int i=0;i<listItems.size();i++)
{
actualItems.add(listItems.get(i).getAttribute("href"));
}
int j = goods.length-1;
for(int i=0;i<goods.length;i++)
{
String actualItem = actualItems.get(i);
String product = goods[j];
System.out.println(product);
//assertTrue(actualItems.get(i).contains(goods[j]));
assertTrue(actualItem.equals(product));
j--;
}
assertEquals(listItems.size(), goods.length,"Assert Number of Items in the Bag");
}
If you don't care about the order, but about the match between provided list of goods and actualItems, you can do this:
Convert input array String[] goods into some collection, for example List. Lets call it goodsList.
From goodsList, remove all items that are also in actualItems.
If resulting set is empty, it means all items from goodsList are
also in actualItems.
If resulting set is not empty, it will contain list of items that are missing in actualItems comparing to goodsList
You can also do the reverse: from actualItems, remove all items that are also contained in goodsList. That gives you list of items that were not present in provided list.
Code:
public void verifyBag(String[] goods) {
actions.clickOn(By.xpath(bagLocator));
List<WebElement> listItems = actions.driver.findElements(By.xpath(bagItems));
List <String> actualItems = new ArrayList<String>();
for(int i=0;i<listItems.size();i++)
{
actualItems.add(listItems.get(i).getAttribute("href"));
}
List<String> goodsList = new ArrayList(Arrays.asList(goods));
goodsList.removeAll(actualItems);
if(goodsList.size() == 0) {
// All goods from provided goods list are also in actualItems
}
else {
// Some items didn't match
}
You have to check the size of goods and actualItems before doing the loop. Make sure that array and list have the same size and both of them is not null or empty.
Function listItems.get(i) and getAttribute("href") can return a null value, please check it before add to list.

Java: find Id By Title () from models

This is my function, to find a id from list by matching titles
public static int findIdByTitle(List<Integer> IDs, List<String> Titles ,String title){
for (int i = 0; i < IDs.size(); i++){
if (Titles.get(i).equals(title))
return IDs.get(i);
}
return 0;
}
This function search in model list and find id
But I can't use this because:
int id = findIdByTitle(Core.userSignIn.getBasicList().getGradeList().get(****?****).getID()
,Core.userSignIn.getBasicList().getGradeList().get(****?****).getName()
,spinnerGrade.getSelectedItem().toString());
I must give it a number position : ( see the lists.get(****?****).getID() or getName()
I want using that's function for all models not just for this model
give 2 lists and a matching word, use matching word to find position of that's in list, and give me a ID of this position
All of my model have ID , Title and some of them have ParentID
with help of Nitin , My problem has been resolved:
List<String> Titles = new ArrayList<>();
List<Integer> IDs = new ArrayList<>();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
Titles = Core.userSignIn.getBasicList().getGradeList().stream().map(GradeList::getGradeName).collect(Collectors.toList());
IDs = Core.userSignIn.getBasicList().getGradeList().stream().map(GradeList::getGradeID).collect(Collectors.toList());
} else {
Titles = new ArrayList<>(Core.userSignIn.getBasicList().getGradeList().size());
IDs = new ArrayList<>(Core.userSignIn.getBasicList().getGradeList().size());
for (GradeList gradeList : Core.userSignIn.getBasicList().getGradeList()) {
Titles.add(gradeList.getGradeName());
IDs.add(gradeList.getGradeID());
}
}
educationList1.setiGradeID(findIdByTitle(IDs
,Titles
,spGrade.getSelectedItem().toString()));
You first have to convert your list to List of Integer and List of String and then pass it to your method. You can use below code if you are using Java 8:
final List<Integer> testList1 = BasicList().getGradeList().stream().map(Test::getId).collect(Collectors.toList());
final List<String> testList2 = BasicList().getGradeList().stream().map(Test::getName).collect(Collectors.toList());
Replace your class name in place of Test in above code.
Use below code for below java 8 env:
List<String> strings = new ArrayList<>(BasicList().getGradeList().size());
for (Test test : BasicList().getGradeList()) {
strings.add(test.getName());
}
Similar for Ids.
You need another loop if you want to get all Ids of your models, you can do something like this :
List<Integer> listId=new ArrayList<Integer>();
for(int i=0; i<BasicList().getGradeList().size(); i++) {
listId.add(findIdByTitle(BasicList().getGradeList().get(i).getID()
,BasicList().getGradeList().get(i).getName()
,spinnerGrade.getSelectedItem().toString()));
}

How to get equal or close to equal amount of objects with different field values from ArrayList

For Example I have ArrayList with Objects.
This objects have some field - pictureName.
One of them really have picture name (lets name them "1st type"), other have just an empty string (2nd type).
size of arrayList = M and can change.
Amount of 1st and 2nd-type objects can be different.
I need to get equal or close to equal amount of 1st type objects and 2nd type objects and add them into another (empty) arraylist. Size of this arraylist is N, and N<=M.
What is the better way to do this?
UPD: I can't set the size of new ArrayList. I just can find out this number (user sets it). But N<=M is always true
Edit
OP clarified their requirements so I have updated my code. I still begin by sectioning into two lists as below, but then I build the final list as follows:
Iterator<MyObject> namesIterator = withNames.iterator();
Iterator<MyObject> noNamesIterator = noNames.iterator();
while (newList.size() < userDefinedSize) {
if (namesIterator.hasNext()) {
newList.add(namesIterator.next());
}
if (noNamesIterator.hasNext() && newList.size() < userDefinedSize) {
newList.add(noNamesIterator.next());
}
}
Original
My strategy is to iterate over the original list and bucket the objects by whether they have a pictureName or not. Then create a new list, and add to that list from my buckets until I use up all the elements in the smallest bucket.
private void myMethod() {
List<MyObject> original = /* your code here */
List<MyObject> withNames = new ArrayList<>();
List<MyObject> noNames = new ArrayList<>();
for (MyObject o : original) {
if (o.pictureName != null) {
withNames.add(o);
}
else {
noNames.add(o);
}
}
int size = Math.min(withNames.size(), noNames.size());
List<MyObject> newList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
newList.add(withNames.get(i));
newList.add(noNames.get(i));
}
// now you have the same number of named and unnamed objects in `newList`
}

Issue with Sorting List using collections in java

I have a list with Order Entries. Each order entry has a base price. I want to sort this list on entry.basePrice descending (enty.basePrice == 0 entries should be at the bottom).
In this list, either no entry will have 0 price or one entry will have. I am doing like this ..
final Collection<AbstractOrderEntryModel> orderEntry = Collections2.filter(source.getEntries(),
new Predicate<AbstractOrderEntryModel>()
{
#Override
public boolean apply(final AbstractOrderEntryModel arg)
{
return arg.getBasePrice().doubleValue() == 0 ? true : false;
}
});
Here I m filtering my entry which having baseprice = 0.0
Now How I will remove and add this item (orderEntry.iterator().next()) at last in OrderEntry List?
If its not a recommended solution, and it can be possible through Collections.sort also then please give me solution.
As far as I understand, you want to put an item matching a predicate at the end of the list. This can be done straightforward:
List<AbstractOrderEntryModel> list=source.getEntries()
final Collection<AbstractOrderEntryModel> orderEntry = Collections2.filter(list,
new Predicate<AbstractOrderEntryModel>()
{
public boolean apply(final AbstractOrderEntryModel arg)
{
return arg.getBasePrice().doubleValue() == 0;
}
});
if(!orderEntry.isEmpty()) {
assert orderEntry.size()==1; // so you said in your question
AbstractOrderEntryModel e=orderEntry.iterator().next();
list.remove(e);
list.add(e);
}

Categories

Resources