0

How do I sum up all the values which are in two different maps?

Map<String, List<String>> map = new HashMap<String, List<String>>();
List<String> totalValOne= new ArrayList<String>();
List<String> totalValTwo= new ArrayList<String>();
map1.put("totalPriceSet1", totalValOne);     
map2.put("totalPriceSet2", totalValTwo);

I'm getting all the values

String PriceValues1 = "";
for (int i = 0; i < map1.size(); i++) {
    System.out.println(map1.size());
    for (List<String> value : map1.values()) {

        for (String tot : value) {
            PriceValues1 = tot;
            System.out.println("values.....  "+ tot);
        }
    }
    //--------

String PriceValues2 = "";
for (int i = 0; i < map2.size(); i++) {
    System.out.println(map2.size());
    for (List<String> value : map2.values()) {

        for (String tot : value) {
            PriceValues2 = tot;
            System.out.println("values.....  "+ tot);
        }
    }

I am trying to add the values of both the maps one by one.

ex:

totalPriceSet1 {1,2,3,4}
totalPriceSet2 {2,3,4,5}

and I want the sum of the two as,

Sum {3,5,7,9}
Sam
  • 513
  • 1
  • 11
  • 27
  • 3
    Is there any reason why you're storing your values as strings, and not integers? – dbrown93 Dec 19 '15 at 09:17
  • Yes, because I am appending `$` sign for all the values. – Sam Dec 19 '15 at 09:31
  • @sam There is a pattern which you should look into [Money as explained by Martin Fowler](http://martinfowler.com/eaaCatalog/money.html) , here is a relevant [post on stackoverflow](http://stackoverflow.com/questions/4145616/how-to-model-an-amount-of-money-in-java) – Pétur Ingi Egilsson Dec 19 '15 at 09:37
  • 1
    @sam You could always store the values as integers, do your number processing, then when you need to display/append the $ sign you can simply use Integer.toString(num) or '"$" + num' – dbrown93 Dec 19 '15 at 10:24

4 Answers4

0

What you can do is:

 public static void main( String[] args ){
        Map<String, Integer> map = new TreeMap<>();
        map.put( "total1", 2 );
        map.put( "total2", 3 );

        Map<String, Integer> map2 = new TreeMap<>();
        map2.put( "otherTotal1", 1 );
        map2.put( "otherTotal2", 2 );

        System.out.println( sumMaps( map, map2 ) );
    }

    private static List<Integer> sumMaps( Map<String, Integer>... maps ){
        List<Integer> result = new ArrayList<>();
        for( Map<String, Integer> map : maps ){
            List<Integer> list = new ArrayList<Integer>( map.values() );

            for( int i = 0; i < list.size(); i++ ){
                if( indexExists( result, i ) ){
                    // sums up existing and new value
                    Integer oldValue = result.get( i );
                    Integer newValue = oldValue + list.get( i );
                    result.remove( i );
                    result.add( i, newValue );
                }
                else{
                    // no existing value
                    result.add( list.get( i ) );
                }
            }
        }

        return result;
    }

    private static boolean indexExists( List<Integer> list, int index ){
        return index >= 0 && index < list.size();
    }

I've made with a Map<String,Integer> you can change it String -> String or whatever you wish.

Output:

[3, 5]
Sercan Ozdemir
  • 4,641
  • 3
  • 34
  • 64
  • Using `HashMap` doesn't guarantee ordering, quite the opposite actually, so result could as easily have been `[4, 4]` or `[5, 3]`. – Andreas Dec 19 '15 at 10:01
  • I am not able to add the values as I am taking it as `Map>` – Sam Dec 19 '15 at 11:13
0

Be aware that if the values are in a HashMap, the ordering is virtually random. LinkedHashMap and TreeMap have well-defined orderings though.

What if maps are not the same size? I'll assume here that you just want the single values too.

Best way is to parallel-iterate the two maps. That way nothing gets copied, and each map is only iterated once.

private static List<Integer> sumMapValues(Map<?, Integer> map1, Map<?, Integer> map2) {
    Iterator<Integer> iter1 = map1.values().iterator();
    Iterator<Integer> iter2 = map2.values().iterator();
    List<Integer> sum = new ArrayList<>();
    while (iter1.hasNext() || iter2.hasNext()) {
        if (! iter2.hasNext())
            sum.add(iter1.next());
        else if (! iter1.hasNext())
            sum.add(iter2.next());
        else
            sum.add(iter1.next() + iter2.next());
    }
    return sum;
}

Test

Map<String, Integer> map1 = new LinkedHashMap<>();
map1.put("a", 1);
map1.put("b", 2);
map1.put("c", 3);
map1.put("d", 4);
Map<String, Integer> map2 = new LinkedHashMap<>();
map2.put("x", 2);
map2.put("y", 3);
map2.put("z", 4);
System.out.println(map1);
System.out.println(map2);
System.out.println(sumMapValues(map1, map2));

Output

{a=1, b=2, c=3, d=4}
{x=2, y=3, z=4}
[3, 5, 7, 4]
Andreas
  • 154,647
  • 11
  • 152
  • 247
0

What I did was,

    private static List<Integer> sumValue(Map<String, List<Integer>> map1,
                                 Map<String, List<Integer>> map2) 
{
        List<Integer> priceValues1Int = new ArrayList<Integer>();
        List<Integer> priceValues2Int = new ArrayList<Integer>();
        List<Integer> sum = new ArrayList<Integer>();
        for (List<Integer> integer : map1.values()) {
            priceValues1Int = integer;
        }
        for (List<Integer> integer2 : map2.values()) {
            priceValues2Int = integer2;
        }
        for(int i=0; i<priceValues1Int .size(); i++){
            int sum1 =  priceValues1Int .get(i)+priceValues2Int .get(i);
            sum.add(sum1);
        }
    return sum;
}
Sam
  • 513
  • 1
  • 11
  • 27
-1

The problem is about lists, not maps. To merge two lists, for example :

public static void main(String... args) {

    // Example
    List<Integer> listA = new ArrayList<>();
    listA.add(1);
    listA.add(2);
    listA.add(3);
    listA.add(4);

    Map<String, List<Integer>> map1 = new HashMap<>();

    map1.put("totalPriceSet1", listA);

    List<Integer> listB = new ArrayList<>();
    listB.add(2);
    listB.add(3);
    listB.add(4);
    listB.add(5);

    Map<String, List<Integer>> map2 = new HashMap<>();
    map2.put("totalPriceSet2", listB);

    // Sum
    List<Integer> sum = sum(map1.get("totalPriceSet1"), map2.get("totalPriceSet2"));

    // Put in third map if you want
    Map<String, List<Integer>> map3 = new HashMap<>();
    map3.put("sum", sum);

    // Output
    System.out.println(map3.get("sum").stream().map(Object::toString).collect(Collectors.joining(",", "{", "}")));

}

public static List<Integer> sum(List<Integer> listA, List<Integer> listB) {
    List<Integer> result = new ArrayList<>();

    Iterator<Integer> iteratorA = listA.iterator();
    Iterator<Integer> iteratorB = listB.iterator();

    while (iteratorA.hasNext() && iteratorB.hasNext()) {
        result.add(iteratorA.next() + iteratorB.next());
    }

    return result;
}
  • Horrendous performance on that Java 8 version, doing sequential search for the element to find it's index, and if you have multiple elements of same value, you the get the wrong index and hence wrong sum. --- And classic version assumes `List`, where indexed lookup is ok, but question was specifically about `Map` values, so way off point here. – Andreas Dec 19 '15 at 10:09
  • @Andreas : I remove the java 8 version, but don't think the problem is about `map`, the asker never use the keys. In other words, the problem is about `map` values, and map values are `collections`. – Mikael Chobert Dec 19 '15 at 10:29
  • Correct, but a `Collection` is not a `List`. `Collection` doesn't even have a get-by-index method, and although all lists do, lists such as `LinkedList` has to search sequentially for the index. Doing get-by-index on anything other than array-backed lists is very bad for performance, and it's unnecessary for this particular problem. – Andreas Dec 19 '15 at 10:42
  • The problem is about the sum of element one by one (based on their index) in a `Collection`. This problem is non deterministic and have no sense if this `Collection` doesn't guarantee ordering, so the problem doesn't concern `Collection`, but `List` (or any other ordering collection). My first sentence. – Mikael Chobert Dec 19 '15 at 12:30
  • And ok for the get-by-index perf aspect, i change my example and use `Iterator`. Thanks. – Mikael Chobert Dec 19 '15 at 12:32