0

I have List of User object, I just want to get a Collect object from List based on variables in User object.

public class User {

    private int id;

    private String sex;

    private int year;

   private int value;

    /**
     * Getter and setter for all variables
     */
}

I have a model class like this. Now I have a list of User objects.

List<User> users = new ArrayList<User>();

I want to create a single object which contains the sum of all the values fro monthly salary

List<Collect> objList = new ArrayList<Collect>();
for(User object : users) {
    if(object.getyear().equals("2013")){
        ageList.add(object);
    }
}

but I am not sure how it will work. As there might be multiple entries in for the same year and I want to sum all the values for the same year and put into the collect object

is there any way where I can create a single object from the list of object and also perform a sum operation based on the same year from the list of object. Also, don't want to hardcode 2013 for checking year.

8
  • So, for example, you want to sum value of all user whose year is 2013? Commented May 22, 2018 at 14:47
  • I don't understand your question. I think you want a reduction operation, but it could be a grouping one? You talk about your User object, but it doesn't have a monthly salary. You talk about a Collect object, but we see nothing of it. Commented May 22, 2018 at 14:47
  • @MạnhQuyếtNguyễn yes Commented May 22, 2018 at 14:48
  • @ifly6 I want to sum all the values for the same years ..for example 2013, 2014 2016 etc. but without hardcoding the year Commented May 22, 2018 at 14:51
  • "single object" is too vague. Can you clarify what do you mean by that? Commented May 22, 2018 at 14:51

3 Answers 3

2

The imperative way to do this, not the streamified way, would be to use a for-loop similar to the way you're already doing it.

What you can do, however, to get the list of all years for which you want, so you don't need to hard code it, is two-fold. First, I would create a Map for years and salary sums (if not loosely typed Map<Year, Salary> although this would probably take the form Map<Integer, Integer>).

Map<Integer, Integer> map = new HashMap<>();

Then, I would run through the list of users initialising the values for the HashMap and adding the values to the initialised values in the HashMap in a single loop.

for (User u : users)
    if (map.containsKey(u.getYear()))
        map.put(u.getYear(), map.get(u.getYear()) + u.getSalary());
    else map.put(u.getYear(), 0);

The map would then contain the sums you want by year. And you would get them by querying map.get(year).

Sign up to request clarification or add additional context in comments.

5 Comments

I can do it with stream :-?
@MạnhQuyếtNguyễn I wonder if your solution can be as flexible as this one. For example, if you suspect that the sum could be too large for an integer.
If the result is too large for int, just use sumToLong
Here, you would have to make two changes. First, you would use Map<Integer, BigInteger> and change it from map.get(u.getYear()) + ... to map.get(u.getYear()).add(new BigInteger(u.getSalary())), assuming that the salary is still an integer.
summingLong. In your code you need that change to. :)
1

You can use an IntStream for that:

long totalSum =  users.stream()
    .filter(user -> user.getYear() == 2013))
    .mapToInt(User::getValue)
    .sum();

Of course you can declare the year in a variable, parameter, read it from commandline, ... to not have it hardcoded.

Comments

1

So you want to sum for every year right, here's the way:

Map<Integer, Integer> totalValuePerYear = users.stream()
                       .collect(groupingBy(User::getYear, summingInt(User::getValue)));

If you want to collect it to a object, such as:

public class SumPerYear {
    private int year;
    private int sum;
    // Getter, setter, constructor
}

You can do one step further:

List<SumPerYear> result = users.stream()
                       .collect(groupingBy(User::getYear, summingInt(User::getValue)))
                       .entrySet().stream()
                       .map(e -> new SumPerYear(e.getKey, e.getValue))
                       .collect(toList());

1 Comment

+1. With the same level of flexibility, IMO, this is more concise and preferable than the imperative version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.