I get a list from the database ingredients, and I make a new list somelist = ingredinets. I convert some values of somelist with convert(somelist). This is changing both lists. Is there a way to keep the original list ingredients? Probably, I am doing something wrong. Should I get a second list from the database?
List <Ingredient> somelist = new ArrayList<>();
somelist = ingredients;
convert.showImperial(somelist);
public List<Ingredient> showImperial(List<Ingredient> ingredients) {
for (int i = 0; i < ingredients.size(); i++) {
switch (ingredients.get(i).getMeasurement()) {
case GRAMS: {
Double value = ingredients.get(i).getValue();
if (value >= 453.59237) {
value = value / 453.59237;
BigDecimal rounded = new BigDecimal(value);
rounded=rounded.setScale(2, RoundingMode.HALF_DOWN);
ingredients.get(i).setValue((rounded.doubleValue())); //to pound
ingredients.get(i).setMeasurement(POUNDS);
} else {
value = value * 16 / 453.59237; //to oz;
System.out.println(value);
BigDecimal rounded = new BigDecimal(value);
rounded = rounded.setScale(1, RoundingMode.HALF_DOWN);
// System.out.println(rounded);
// System.out.println(rounded.doubleValue());
ingredients.get(i).setValue(rounded.doubleValue());
ingredients.get(i).setMeasurement(OUNCE);
}
break;
}
case ML: {
double value = ingredients.get(i).getValue();
ingredients.get(i).setValue(value / 240);
ingredients.get(i).setMeasurement(CUP); //to cup
break;
}
default: {
break;
}
}
}
return ingredients;
}
This line:
somelist = ingredients;
Is not making a copy of ingredients, it's setting somelist to be the same as ingredients.
You can simply add all the elements from ingredients to somelist:
somelist.addAll(ingredients);
...but you also appear to be modifying those, and a List holds a reference to the elements, not the actual elements. So you'll need to go a step further and copy one level deeper:
for (Ingredient ingr : ingredients) {
somelist.add(new Ingredient(ingr)); // or use whatever constructor is appropriate.
}
What you're doing is setting the second list to be a reference to the first. What you want to do is somehow pass the information from the first to the second. Otherwise when one is changed, so is the other.
If you are using an ArrayList as an implementation in somelist you can just create using this constructor.
List <Ingredient> somelist = new ArrayList<>(ingredients);
Note that this is a copy of List, if you add some elements into ingredients won't be reflected in someList and viceversa.
Example:
List <Ingredient> somelist = new ArrayList<>(ingredients);
ingredients.add(new Ingredient()); // won't be reflected in somelist
But if you mutate elements from the list for example via setters then it will reflected in both list.This is a shallow copy.
List <Ingredient> somelist = new ArrayList<>(ingredients);
Ingredient aux=ingredients.get(0);
aux.setSomeProperty("someProperty");//will be reflected in both list
To make a deep copy you have to add a clone method for your Ingredient class to make a deep copy.
Related
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);
I'm stuck in the following problem:
I have a dynamic List of items defined like this:
List<Object> itemList = ArrayList(ArrayList<Object1, Object2, Double[]>)
The Object1 and Object2 are not of interest here, but the array Double[] which contains an arbitrary number of entries.
In my code I iterate over the outer ArrayList and try to calculate the cartesianProduct of guava. Up to now I have something like (partly not working code, sorry ...):
private Set<List<Set<Double>>> getValueCombinations() {
List<Set<Double>> valuesOfInnerArrays = new ArrayList<>();
// Loop over the list of device data sets in the class and add the trim value vectors to a list for further
// processing and cartesian prooduct generation.
for (Integer indexCounter = 0; indexCounter < OuterArrayList.size(); indexCounter++) {
final List<Object> innerDataSet = (List<Object>) OuterArrayList.get(indexCounter);
final Set<Double> innerDoubleArray = ImmutableSet.of(((List<Double>) innerDataSet.get(2)).toArray(new Double[]));
valuesOfInnerArrays.add(innerDoubleArray);
}
ImmutableList<Set<Double>> test = ImmutableList.of(valuesOfInnerArrays)
// generate Cartesian product of all trim vectors = a n x m matrix of all combinations of settings
final Set<List<Set<Double>>> cartesianProduct = Sets.cartesianProduct(ImmutableList.of(valuesOfInnerArrays));
return cartesianProduct;
}
In all the examples I found, they always call cartesianProduct with known Sets, which I cannot do:
Set<Double> first = ImmutableSet.of(1., 2.);
Set<Double> second = ImmutableSet.of(3., 4.);
Set<List<Double>> result =
Sets.cartesianProduct(ImmutableList.of(first, second));
What I would like to have in the end are all cominations of the numbers stored in the inner Double[] arrays.
Any help appreciated.
Thanks to the Post "Java Guava CartesianProduct" I solved my problem. My final solution looks like this:
private Set<List<Double>> getValueCombinations() {
final List<Set<Double>> valuesOfInnerArrays = new ArrayList<>();
// Loop over the list of device data sets in the class and add the value vectors to a list for further
// processing and cartesian product generation.
for (Integer indexCounter = 0; indexCounter < outerArrayList.size(); indexCounter++) {
final List<Object> innerDataSet = (List<Object>) deviceDataSets.get(indexCounter);
final SortedSet<Double> >innerDoubleArray = new TreeSet<>((List<Double>) innerDataSet.get(2));
valuesOfInnerArrays.add(innerDoubleArray);
}
return Sets.cartesianProduct(valuesOfInnerArrays);
}
Additionally I changed the format of my input list:
List<Object> itemList = ArrayList(ArrayList<Object1, Object2, List<Double>>)
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`
}
I am storing scores in a ArrayList, but when the user has a score equal to a previous score, the second one is not added to the ArrayList. How can I add equal values to a ArrayList (or use another type of List)?
Code:
[...]
ArrayList<String> savedArray = new ArrayList<>();
Set<String> gandula = new HashSet<>();
[...]
public Preferencias(Context contextoParametro) {
contexto = contextoParametro;
preferences = contexto.getSharedPreferences(NOME_ARQUIVO, MODE);
editor = preferences.edit();
}
public void addMediaGeral(double mediaGeral) {
//Save Score
Set<String> set = new HashSet<String>();
if (!getMediaGeral().get(0).equals("0")) {
savedArray.addAll(getMediaGeral());
}
savedArray.add(String.valueOf(mediaGeral));
set.addAll(savedArray);
editor.putStringSet(KEY_MEDIA_GERAL, set);
editor.commit();
}
public ArrayList<String> getMediaGeral(){
//get score
Set<String> set = preferences.getStringSet(KEY_MEDIA_GERAL, gandula);
ArrayList<String> list = new ArrayList<String>(set);
return list;
}
[...]
Retrieving in my activity:
[...]
mediaGeral = score;
preferencias.addMediaGeral(Double.parseDouble(mediaGeral));
[...]
ArrayList<String> string_medias = new ArrayList<>();
string_medias = preferencias.getMediaGeral();
ArrayList<Float> float_medias = new ArrayList<>();
for (int j = 0; j < string_medias.size(); j++){
float_medias.add(Float.parseFloat(string_medias.get(j)));
}
Log.i("TESTANDO PRF", "TAMANHO DA LISTA: "+float_medias.size());
Float[] dataObjects = float_medias.toArray(new
Float[float_medias.size()]);
doChart(float_medias);
[...]
I scored 0.33333 three times (I'll config decimal places) but it is showing only one score 0.3333.
Printscreen: http://prntscr.com/f1vx3h
But the chart accepts duplicates. Printscreen: http://prntscr.com/f1vxng (i manipulated the scores in the last printscreen).
A Set does not allow for duplicate values.
Doing this:
set.addAll(savedArray);
discards all your duplicates.
These answers may be of help.
Saving a JSON object as a string in preferences would probably be the way to go.
ArrayList accept duplicate this should not be your problem but I saw that your store yours score in a HashSet uses a hashMap instead because:
In the case of HashMap, it replaces the old value with the new one.
In the case of HashSet, the item isn't inserted.
I have a mapper method which takes list of entities called Claim iterates over them and maps to CompensationDTO and adds to list, but entity can contain lists of children entities which type is also Claim and those children can also contain list of Claims, so to iterate over them all is best to use recursion but i'm not sure how it should be written
private List<CompensationDTO> mapToDTO(List<Claims> claims) {
List<CompensationsDTO> compensations = new ArrayList<>();
if (claims.isEmpty()) {
return new ArrayList<>();
}
for (Claim claim : claims) {
CompensationDTO compensationDTO = new CompensationDTO();
compensationDTO.setId(claim.getId());
compensationDTO.setAmount(claim.getAmount());
compensationDTO.setType(claim.getType());
compensations.add(compensationDTO);
mapToDTO(claim.getChildrenClaims());
}
return compensations;
}
I understand that the base case should return empty list but i don't know where to put the recursive function call mapToDTO(claim.getChildrenClaims());
Did you try to add compansations.addAll()?:
private List<CompensationDTO> mapToDTO(List<Claims> claims) {
List<CompensationsDTO> compensations = new ArrayList<>();
if (claims.isEmpty()) {
return new ArrayList<>();
}
for (Claim claim : claims) {
CompensationDTO compensationDTO = new CompensationDTO();
compensationDTO.setId(claim.getId());
compensationDTO.setAmount(claim.getAmount());
compensationDTO.setType(claim.getType());
compensations.add(compensationDTO);
compensations.addAll(mapToDTO(claim.getChildrenClaims()));
}
return compensations;
}
mapToDTO returns List<CompensationDTO> and you need to add these elements to your local list.
List<CompensationDTO> rec = mapToDTO(claim.getChildrenClaims());
compensations.addAll(rec);