5

Create a third array list by summing up data related to same element if present in both lists, else insert the new data

I created two maps from the two array lists with Id as key and then created a set by combining keys from both maps. Making use of the values in set, i queried both the lists and arrived at the sum. I am seeing the expected output if i follow this method, but wanted to know if there is any other efficient way of achieving this in Java 1.6

----------------Java----------------

public class Stock {

    private int stockCode;
    private int stockQuantity;
    private int stockValue;

    public int getStockCode() {
        return stockCode;
    }

    public int getStockQuantity() {
        return stockQuantity;
    }

    public int getStockValue() {
        return stockValue;
    }

    public Stock(int stockCode, int stockQuantity, int stockValue) {
        this.stockCode = stockCode;
        this.stockQuantity = stockQuantity;
        this.stockValue = stockValue;
    }

    public static void main(String[] args){
        List<Stock> oldStock = new ArrayList<Stock>();
        Stock s1 = new Stock(1,  20, 16000);
        Stock s2 = new Stock(2, 10, 5000);
        Stock s3 = new Stock(3,  15, 3000);
        oldStock.add(s1);
        oldStock.add(s2);
        oldStock.add(s3);

        List<Stock> newStock = new ArrayList<Stock>();
        Stock s4 = new Stock(5, 5, 2500);
        Stock s5 = new Stock(1, 10, 8000);
        Stock s6 = new Stock(3, 10, 2000);
        newStock.add(s4);
        newStock.add(s5);
        newStock.add(s6);

        List<Stock> netStock = new ArrayList<Stock>();

        Map<Integer, Stock> oldStockMap = new HashMap<Integer, Stock>();
        for(Stock os:oldStock){
            oldStockMap.put(os.getStockCode(),os);
        }
        Map<Integer, Stock> newStockMap = new HashMap<Integer, Stock>();
        for(Stock ns:newStock){
            newStockMap.put(ns.getStockCode(),ns);
        }
        Set<Integer> keySet = new HashSet<Integer>();
        keySet.addAll(oldStockMap.keySet());
        keySet.addAll(newStockMap.keySet());

        for(Integer ks:keySet){
            Integer netStockQ=0;
            Integer netStockV=0;
            if(oldStockMap.get(ks)!=null && newStockMap.get(ks)!=null) {
                netStockQ =oldStockMap.get(ks).getStockQuantity() + newStockMap.get(ks).getStockQuantity();
                netStockV = oldStockMap.get(ks).getStockValue() + newStockMap.get(ks).getStockValue();
            } else if(oldStockMap.get(ks)==null && newStockMap.get(ks)!=null){
                netStockQ = newStockMap.get(ks).getStockQuantity();
                netStockV = newStockMap.get(ks).getStockValue();
            } else if(oldStockMap.get(ks)!=null && newStockMap.get(ks)==null){
                netStockQ =oldStockMap.get(ks).getStockQuantity();
                netStockV = oldStockMap.get(ks).getStockValue();
            }
            netStock.add(new Stock(ks,netStockQ, netStockV));
        }

        for(Stock ns: netStock){
            System.out.println(ns.getStockCode() +"- Quantity - "+ ns.getStockQuantity()+"- Value -"+ns.getStockValue());
        }
    }
}

---------------Output---------------

1- Quantity - 30- Value -24000
2- Quantity - 10- Value -5000
3- Quantity - 25- Value -5000
5- Quantity - 5- Value -2500
3
  • 9
    Java 6 is no longer supported, it would be a great time to upgrade because there are many more efficient ways to accomplish your current algorithm with Java 8+. If you really can't upgrade from Java 6, and this code works; I'd leave it alone. Commented Sep 12, 2019 at 4:56
  • 1
    If you are using Java 1.6, how can you use diamond operators (e.g.: new HashMap<>()) in your code, which are only supported after Java 7? Commented Sep 12, 2019 at 5:06
  • 1
    @ElliottFrisch - Well i am kinda stuck with java 6 for now .. Commented Sep 12, 2019 at 5:06

4 Answers 4

5

You can do the following (given that you cannot upgrade to Java 8)

  • Create a Map with stock code as key and stock as the value
Map<Integer, Stock> netStockMap = new HashMap<Integer, Stock>();
  • Then add all the old stock entries to that map as follows.
for (Stock oldStockItem: oldStock) {
    netStockMap.put(oldStockItem.getStockCode(), oldStockItem);
}
  • Then for each new stock entry, check if an old entry exists in the map. If exists, create a new stock entry combining both old and new entry. Otherwise just add the new stock entry to the map.
for (Stock newStockItem: newStock) {
    Integer stockCode = newStockItem.getStockCode();
    Stock oldStockItem = netStockMap.get(stockCode);
    if (oldStockItem != null) {
        Stock netStockItem = new Stock(stockCode, oldStockItem.getStockQuantity() + newStockItem.getStockQuantity(),oldStockItem.getStockValue() + newStockItem.getStockValue());
        netStockMap.put(stockCode, netStockItem);

    } else {
        netStockMap.put(stockCode, newStockItem);
    }
}
  • Then get the values of the map as the final stock list
List<Stock> netStock = new ArrayList<Stock>(netStockMap.values());
Sign up to request clarification or add additional context in comments.

1 Comment

It does make sense to use only one map instead of two. Thank you
4

If you can upgrade to Java 8, then you can efficiently achieve it through Streams.

You can use Streams to group these items based on ID and then sum their values and finally collect them as a list like:

List<Stock> netStock = new ArrayList<Stock>(oldStock);
netStock.addAll(newStock);

netStock = new ArrayList<>(netStock.stream().collect(
        Collectors.toMap(Stock::getStockCode, Function.identity(), (Stock i1, Stock i2) -> {
            i1.setStockQuantity(i1.getStockQuantity()+i2.getStockQuantity());
            i1.setStockValue(i1.getStockValue()+i2.getStockValue());
            return i1;
        })).values());

Output:

1- Quantity - 30- Value -24000
2- Quantity - 10- Value -5000
3- Quantity - 25- Value -5000
5- Quantity - 5- Value -2500

Also you need to create setter methods for your fields in Stock class

Comments

2

I think that you don't need to use the 2 maps you're using (oldStockMap and newStockMap). You can use only one map, at first insert all the elements from one list, and later update elements that are repeated in second list or add elements that are not reapeated in second list. The complexity is the same, but with a little factor improvement.

public class Stock {

    private int stockCode;
    private int stockQuantity;
    private int stockValue;

    public int getStockCode() {
        return stockCode;
    }

    public int getStockQuantity() {
        return stockQuantity;
    }

    public int getStockValue() {
        return stockValue;
    }

    public Stock(int stockCode, int stockQuantity, int stockValue) {
        this.stockCode = stockCode;
        this.stockQuantity = stockQuantity;
        this.stockValue = stockValue;
    }

    public static void main(String[] args){
        List<Stock> oldStock = new ArrayList<Stock>();
        Stock s1 = new Stock(1,  20, 16000);
        Stock s2 = new Stock(2, 10, 5000);
        Stock s3 = new Stock(3,  15, 3000);
        oldStock.add(s1);
        oldStock.add(s2);
        oldStock.add(s3);

        List<Stock> newStock = new ArrayList<Stock>();
        Stock s4 = new Stock(5, 5, 2500);
        Stock s5 = new Stock(1, 10, 8000);
        Stock s6 = new Stock(3, 10, 2000);
        newStock.add(s4);
        newStock.add(s5);
        newStock.add(s6);

        Map<Integer, Stock> netStockMap = new HashMap<Integer, Stock>();

        for(Stock os:oldStock){
            netStockMap.put(os.getStockCode(),os);
        }

        for(Stock ns:newStock){
            Integer code = ns.getStockCode();
            if(netStockMap.get(ns.getStockCode()) != null) {
                Integer netStockQ = netStockMap.get(code).getStockQuantity() + ns.getStockQuantity();
                Integer netStockV = netStockMap.get(code).getStockValue() + ns.getStockValue();
                netStockMap.put(code, new Stock(code, netStockQ, netStockV));
            } else {
                netStockMap.put(code,ns);
            }
        }

        List<Stock> netStock = new ArrayList<Stock>();
        netStock.addAll(netStockMap.values());

        for(Stock ns: netStock){
            System.out.println(ns.getStockCode() +"- Quantity - "+ ns.getStockQuantity()+"- Value -"+ns.getStockValue());
        }
    }
}

Comments

2

I would rather add a StockCollector to reduce unnecessary iterations over collections and eliminate redundant maps and lists.

class StockCollector {

    private Map<Integer, Stock> stockMap = new HashMap<Integer, Stock>();

    public void addStock(List<Stock> stock) {
         for(Stock s: stock) {
             Stock oldStock = stockMap.get(s.getStockCode());
             Integer netStockQ = 0;
             Integer netStockV = 0;
             if(oldStock != null) {
                 netStockQ = oldStock.getStockQuantity() + s.getStockQuantity();
                 netStockV = oldStock.getStockValue() + s.getStockValue();                     
             } else {
                 netStockQ = s.getStockQuantity();
                 netStockV = s.getStockValue();
             }
             stockMap.put(new Stock(s.getStockCode(), netStockQ, netStockV));
         }
    }

    public Collection<Stock> getStock() {
         return stockMap.values();
    }
}

Then your may add stocks as many as you want:

StockCollector collector = new StockCollector();
collector.addStock(oldStock);
collector.addStock(newStock);

for(Stock ns: collector.getStock()){
    System.out.println(ns.getStockCode() +"- Quantity - "+ ns.getStockQuantity()+"- Value -"+ns.getStockValue());
}

1 Comment

this approach seems cleaner. Thank you

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.