Sum Values from Specific Field of the Objects in a List

Sum values from specific field of the objects in a list

You can do

int sum = lst.stream().filter(o -> o.getField() > 10).mapToInt(o -> o.getField()).sum();

or (using Method reference)

int sum = lst.stream().filter(o -> o.getField() > 10).mapToInt(Obj::getField).sum();

How to Sum up the attribute values of objects in a list having particular IDs and assign it to another object using Streams

The totalPaid field is not modified because your MyLoan instance with id 23490l is encountered before the other two MyLoans.

As @Silvio Mayolo has suggested in the comments you should first compute the total amount with a temp variable and then assign it to the totalPaid field of the MyLoan instance with id 23490l.

This is a stream implementation of what you were trying to do:

//If to make sure that the element MyLoan invoking the setter is actually present
if (myLoan.stream().map(MyLoan::getLoanId).anyMatch(value -> value == 23490l)){
myLoan.stream()
.filter(loan -> loan.getLoanId() == 23490l)
.findFirst()
.get()
.setTotalPaid(myLoan.stream()
.filter(loan -> loan.getLoanId() == 23491l || loan.getLoanId() == 23492l)
.map(MyLoan::getLoanAmount)
.reduce(BigDecimal.valueOf(0), (a, b) -> a = a.add(b)));
}

WARNING

The method get(), invoked on the Optional retrieved with the terminal operation findFirst(), could throw a NoSuchElementException if a MyLoan with id 23490l is not present within the list. You should first make sure that the element is present, as I've done with my if statement.

A second (bad practice) could involve catching the NoSuchElementException thrown by the get(), in case the desired MyLoan is not present. As it has been pointed out in the comments, catching a RuntimeException (NoSuchElementException is a subclass of it) is a bad practice, as we should investigate on the origin of the problem rather than simply catching the exception. This second approach was honestly a (lazy) last resort only to show another possible way of handling the case.

How to sum up the individual fields of the object list and return the results as a single object

Let introduce class NutritionAccumulator:

class NutritionAccumulator{
private double fat = 0.;
private double carbs = 0.;
private double fiber = 0.;
private double protein = 0.;

public NutritionAccumulator() {
}

public NutritionAccumulator(double fat, double carbs, double fiber, double protein) {
this.fat = fat;
this.carbs = carbs;
this.fiber = fiber;
this.protein = protein;
}

public NutritionAccumulator add(NutritionAccumulator that){
return new NutritionAccumulator(this.fat + that.fat,
this.carbs + that.carbs,
this.fiber + that.fiber,
this.protein + that.protein
);
}
}

And now we can write simple stream reduce:

Optional.ofNullable(response.body())
.stream()
.reduce(
new NutritionAccumulator(),
(acc, fudNut) -> new NutritionAccumulator(
fudNut.getTotalFat(),
fudNut.getTotalCarbohydrate(),
fudNut.getDietaryFiber(),
fudNut.getProtein()
).add(acc),
NutritionAccumulator::add

);

And finally you can pass result from above to builder.

java 8 sum field from list of object with common multiple fields

Here's a possibility : use a composite Key to group at once :

.collect(Collectors.groupingBy(DetailDto::key, Collectors.summarizingInt(DetailDto::getPrice)))

See the definition of Key in DetailDto.java (and notice its eclipse generated hashCode and equals methods):

import java.io.Serializable;

@SuppressWarnings("serial")
public class DetailDto implements Serializable {
String category1;
Integer category2;
Integer price;

transient Integer totalPrice;

public DetailDto() {
}

public DetailDto(String category1, Integer category2, Integer price, Integer totalPrice) {
super();
this.category1 = category1;
this.category2 = category2;
this.price = price;
this.totalPrice = totalPrice;
}

public String getCategory1() {
return category1;
}

public void setCategory1(String category1) {
this.category1 = category1;
}

public Integer getCategory2() {
return category2;
}

public void setCategory2(Integer category2) {
this.category2 = category2;
}

public Integer getPrice() {
return price;
}

public void setPrice(Integer price) {
this.price = price;
}

public Integer getTotalPrice() {
return totalPrice;
}

public void setTotalPrice(Integer totalPrice) {
this.totalPrice = totalPrice;
}

Key key() {
return new Key(category1, category2, price);
}

}
class Key {
String category1;
Integer category2;
Integer price;

public Key(String category1, Integer category2, Integer price) {
super();
this.category1 = category1;
this.category2 = category2;
this.price = price;
}
public String getCategory1() {
return category1;
}
public Integer getCategory2() {
return category2;
}
public Integer getPrice() {
return price;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((category1 == null) ? 0 : category1.hashCode());
result = prime * result + ((category2 == null) ? 0 : category2.hashCode());
result = prime * result + ((price == null) ? 0 : price.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (category1 == null) {
if (other.category1 != null)
return false;
} else if (!category1.equals(other.category1))
return false;
if (category2 == null) {
if (other.category2 != null)
return false;
} else if (!category2.equals(other.category2))
return false;
if (price == null) {
if (other.price != null)
return false;
} else if (!price.equals(other.price))
return false;
return true;
}
}

Main.java

import java.io.IOException;
import java.util.IntSummaryStatistics;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;

public class Main {

public static void main(String[] args) throws IOException {
DetailDto[] values = new ObjectMapper().readerFor(DetailDto[].class)
.readValue(Main.class.getResourceAsStream("data.json"));
// for (DetailDto dto : values) {
// display(dto);
// }

Map<Key, IntSummaryStatistics> res = Stream.of(values)
.collect(Collectors.groupingBy(DetailDto::key, Collectors.summarizingInt(DetailDto::getPrice)));

Stream<DetailDto> agg = res.entrySet().stream().map(e -> new DetailDto(e.getKey().category1,
e.getKey().category2, e.getKey().price, (int) e.getValue().getSum()));

agg.forEach(Main::display);

}

protected static void display(DetailDto dto) {
final ObjectWriter json = new ObjectMapper().writerFor(DetailDto.class).withDefaultPrettyPrinter();
try {
System.out.println(json.writeValueAsString(dto));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}

HTH!

Sum a list of objects based on BigDecimal field in single line

list.stream().map(foo -> foo.field).reduce(BigDecimal.ZERO, (a, b) -> a.add(b));

How to sum up values of same field in array of objects?

You can use reduce() to do that.

Iterate on given data and if an item with same category as current item exists, then add the amount, else add current item as a new entry.

const data = [  { category: 'shopping', amount: 50 },   { category: 'rent', amount: 1000 },   { category: 'groceries', amount: 20 },   { category: 'shopping', amount: 50 }];
let result = data.reduce((acc, curr) => { let item = acc.find(item => item.category === curr.category);
if (item) { item.amount += curr.amount; } else { acc.push(curr); }
return acc;}, []);
console.log(result);

Sum of attribute value in Object List

Assuming you have a list of OrderItems, we can group them by ownerName and do a sum as a downstream collector:

List<OrderItem> items = List.of(
new OrderItem(1,"item1","John",12.00);
new OrderItem(2,"item2","John",385.00);
new OrderItem(3,"item3","John",20.00);
new OrderItem(4,"item4","Doe",19.00));

Map<String, Double> result = items.stream()
.collect(Collectors.groupingBy(OrderItem::ownerName,
Collectors.summingDouble(OrderItem::value)));

From the result map we can get each value by the owner name:

System.out.println(result.get("John")); //prints 417.00

Sum of int from list of object

You can create a Stream of your accounts using stream(), map that stream to the amount of each account using mapToInt and sum the resulting IntStream using IntStream.sum().

List<Account> accounts = new ArrayList<>();
int totalAmount = accounts.stream().mapToInt(Account::getAmount).sum();

This code assumes that there is a getter getAmount for amount.

How to sum a particular number field present in all objects inside an array in mongodb document

To avoid $unwind if you want to get the total for each document, you can use this aggregation stage:

db.collection.aggregate([
{
"$project": {
"sum": {
"$sum": "$score.runsScored"
}
}
}
])

The trick here is using $score.runsScored it generates an array with all values, then you only have to $sum these values.

Example here

The other way is using $unwind and $group like this. Note that in this example _id is null to sum all values in the collection, to get the total for each document you have to use _id: $_id like this example



Related Topics



Leave a reply



Submit