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 MyLoan
s.
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
Why Do == Comparisons with Integer.Valueof(String) Give Different Results for 127 and 128
How to Get Backspace \B to Work in Eclipse's Console
Java's Date(...) Constructor Is Deprecated; What Does That Mean
How to Test That No Exception Is Thrown
What Is the Easiest Way to Ignore a JPA Field During Persistence
Java 8 Method Reference Unhandled Exception
Change Location of Log4J.Properties
What Is the Replacement for Javax.Activation Package in Java 9
Consider Defining a Bean of Type 'Package' in Your Configuration [Spring-Boot]
Highlights Substring in the Tablecell(S) Which Is Using for Jtable Filetering
What Is the Purpose of Defining a Package in a Java File
Javac Not Working in Windows Command Prompt
Do Any Jvm's Jit Compilers Generate Code That Uses Vectorized Floating Point Instructions
Multiple Runnable Classes Inside Jar, How to Run Them
Are Non-Capturing Groups Redundant