Showing posts with label Collection. Show all posts

How to sum values from List, Set and Map using stream in Java 8?



Following examples shows how you can use java 8 Stream api to do summation of Integer, Double and Long in List, Set and Map.

Source code (Item.java)
public class Item {

    private Long id;
    private String name;
    private Double price;
    
    public Item(String name, Double price) {
        this.name = name;
        this.price = price;
    }
    
    /* getter - setter */

    public Double getPrice() {
        return price;
    }

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

List
  • Summation of Integers in List.
  • Summation of Price from List of beans(Item).

Source code (ListStreamSum.java)
import com.javaquery.bean.Item;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Summation of element in List using Stream api in java 8.
 *
 * @author javaQuery
 * @date 17th October, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class ListStreamSum {

    public static void main(String[] args) {
        /* Summation of Integers in List */
        List<Integer> integers = new ArrayList<>(Arrays.asList(10, 20, 30));

        Integer integerSum = integers.stream().mapToInt(Integer::intValue).sum();
        System.out.println("summation: " + integerSum);

        /* Summation when you have list of beans */
        Item motoG = new Item("MotoG", 100.12);
        Item iPhone = new Item("iPhone", 200.12);

        List<Item> listBeans = new ArrayList<>(Arrays.asList(motoG, iPhone));

        Double doubleSum = listBeans.stream().mapToDouble(Item::getPrice).sum();
        System.out.println("summation: " + doubleSum);
    }
}

Output
summation: 60
summation: 300.24

Set
  • Summation of Integers in Set.
  • Summation of Price from Set of beans(Item).

Source code (SetStreamSum.java)
import com.javaquery.bean.Item;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * Summation of element in Set using Stream api in java 8.
 *
 * @author javaQuery
 * @date 17th October, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class SetStreamSum {

    public static void main(String[] args) {
        /* Summation of Integers in Set */
        Set<Integer> integers = new HashSet<>(Arrays.asList(10, 20, 30));

        Integer integerSum = integers.stream().mapToInt(Integer::intValue).sum();
        System.out.println("summation: " + integerSum);

        /* Summation when you have set of beans */
        Item motoG = new Item("MotoG", 100.12);
        Item iPhone = new Item("iPhone", 200.12);

        Set<Item> listBeans = new HashSet<>(Arrays.asList(motoG, iPhone));

        Double doubleSum = listBeans.stream().mapToDouble(Item::getPrice).sum();
        System.out.println("summation: " + doubleSum);
    }
}

Output
summation: 60
summation: 300.24

Map
  • Summation of Integers in Map as a value.
  • Summation of Integers in List as a value.
  • Summation of Price from List of beans(Item) in Map.

Source code (MapStreamSum.java)
import com.javaquery.bean.Item;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Summation of element in Map using Stream api in java 8.
 *
 * @author javaQuery
 * @date 17th October, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class MapStreamSum {

    public static void main(String[] args) {
        /* Summation of Integers in Map */
        Map<String, Integer> integers = new HashMap<>();
        integers.put("A", 10);
        integers.put("B", 20);
        integers.put("C", 30);

        Integer integerSum = integers.values().stream().mapToInt(Integer::intValue).sum();
        System.out.println("summation: " + integerSum);

        /* Summation when you have List/Set in Map */
        Map<String, List<Integer>> listInMap = new HashMap<>();
        listInMap.put("even_numbers", new ArrayList<>(Arrays.asList(2, 4, 6)));

        integerSum = listInMap.values().stream()
                .flatMapToInt(list -> list.stream().mapToInt(Integer::intValue))
                .sum();
        System.out.println("summation: " + integerSum);

        /* Summation when you have List/Set of beans in Map */
        Item motoG = new Item("MotoG", 100.12);
        Item iPhone = new Item("iPhone", 200.12);

        List<Item> items = new ArrayList<>(Arrays.asList(motoG, iPhone));

        Map<String, List<Item>> itemMap = new HashMap<>();
        itemMap.put("items", items);

        Double doubleSum = itemMap.values().stream()
                .flatMapToDouble(list -> list.stream().mapToDouble(Item::getPrice))
                .sum();
        System.out.println("summation: " + doubleSum);
    }
}

Output
summation: 60
summation: 12
summation: 300.24

What is the difference between List, Set and Map in Java?

List , Set , Map in Java8

List interface
An ordered collection (also known as a sequence).

Characteristics
  • Element added from 0th index, 1st, 2nd, ... nth (Sequentially).
  • List allows to insert/update/read element at specific index.
  • List allows duplicate values.
  • It maintains insertion position (1st point).
  • It allows null value.

ArrayList is one of the popular implementation of List used by programmers.

Examples


Set interface
Collection which don't allows duplicate values.

Characteristics
  • Unlike List, Set will not allow index based insert/update/read.
  • Set doesn't allow duplicate. e1 and e2 such that e1.equals(e2)
  • It doesn't maintain insertion position (unordered collection). However you can maintain order using LinkedHashSet.
  • It allows null value.

HashSet is one of the popular implementation of Set used by programmers.

Examples


Map interface
Collection to hold [KEY, VALUE] data.

Characteristics
  • Unlike List, Map will not allow index based insert/update/read.
  • Map doesn't allow duplicate KEY.
  • It doesn't maintain insertion position (unordered collection). However you can maintain order using LinkedHashMap.
  • It allows one null KEY and n number of null VALUE.

HashMap us one of the popular implementation of Map used by programmers.



Collection Framework examples in Java 8

How to convert List of data to Set of data and vice versa in Java?

Following excerpt shows how you can convert List<T> to Set<T> and Set<T> to List<T> in java.

Source code (ListToSet.java)
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * List to Set example.
 *
 * @author javaQuery
 * @date 7th October, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class ListToSet {

    public static void main(String[] args) {
        /* Create list of string */
        List<String> strings = new ArrayList<String>();
        strings.add("A");
        strings.add("B");

        Set<String> stringSet = new HashSet<String>(strings);
        /**
         * new HashSet(Collection<? extends E> c) 
         * We created Set of String so we can initialize HashSet using any collection that extends String.
         */
        
        for (String string : stringSet) {
            System.out.println(string);
        }
    }
}
You would like to read How to Initialize List in declaration?.

Source code (SetToList.java)
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Set to List example.
 *
 * @author javaQuery
 * @date 7th October, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class SetToList {

    public static void main(String[] args) {
        /* Create set of string */
        Set<String> strings = new HashSet<String>();
        strings.add("A");
        strings.add("B");

        List<String> list = new ArrayList<>(strings);
        /**
         * new ArrayList(Collection<? extends E> c) 
         * We created List of String so we can initialize ArrayList using any collection that extends String.
         */
        
        for (String string : list) {
            System.out.println(string);
        }
    }
}
You would like to read How to Initialize Set in declaration?.

Output
A
B

How Fail Fast Iterator identifies that the collection is modified?



Image gives you the abstract idea about How iterator identifies the modification on collection. Its one of the interview question asked as sub part of Fail Fast vs Fail Safe Iterator in Java. To understand it better I pulled out the source code of HashMap.

Source code (HashMap.java)
public class HashMap<K, V>...{
    transient int modCount;

    public V put(K key, V value) {
        return this.putVal(hash(key), key, value, false, true);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        ...
        ++this.modCount;
        ...
    }
 
    public Set<Map.Entry<K,V>> entrySet() {
        // this method internally uses HashIterator
    }

    abstract class HashIterator{
        int expectedModCount;  // for fast-fail
        ...
        HashIterator() {
            expectedModCount = modCount;
            ...
        }
 
        final Node nextNode() {
            ...
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            ...
            ...
        }
    }
}
So when you call method entrySet() of HashMap, It creates the object of inner class HashIterator with current value of modCount and set it in expectedModCount.

Now when nextNode() method is called it compares value of expectedModCount with parent class's (HashMap) modCount and if its not same then it throws ConcurrentModificationException.

Source code (FailFastExample.java)
/**
 * Example of Fail Fast using Map.
 * @author javaQuery
 * @date 4th August, 2016
 * @Github: https://github.com/javaquery/Examples 
 */
public class FailFastExample {
    public static void main(String[] args) {
        Map<String, Double> carPrice = new HashMap<String, Double>();
        carPrice.put("Porsche", 100000D);
        carPrice.put("Ferrari", 200000D);

        /* Iterate over Map */
        for(Map.Entry<String, Double> car : carPrice.entrySet()){
            System.out.println("Car: " + car.getKey());
            System.out.println("Price: " + car.getValue());
            
            /* Will cause java.util.ConcurrentModificationException */
            carPrice.put("Lamborghini", 300000D);
        }
    }
}

Output
Car: Ferrari
Price: 200000.0
Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
 at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
 at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
 at com.javaquery.collections.map.FailFastExample.main(FailFastExample.java:23)

Fail Fast vs Fail Safe Iterator in Java

Fail Fast vs Fail Safe


One of the popular interview question asked to java developer. To know how well you understand the iterator.

Fail Fast
When you perform add, update or remove on collection while iterating on it. It throws java.util.ConcurrentModificationException.

Source code (FailFastExample.java)
import java.util.HashMap;
import java.util.Map;

/**
 * Example of Fail Fast using Map.
 * @author javaQuery
 * @date 4th August, 2016
 * @Github: https://github.com/javaquery/Examples 
 */
public class FailFastExample {
    public static void main(String[] args) {
        Map<String, Double> carPrice = new HashMap<String, Double>();
        carPrice.put("Porsche", 100000D);
        carPrice.put("Ferrari", 200000D);

        /* Iterate over Map */
        for(Map.Entry<String, Double> car : carPrice.entrySet()){
            System.out.println("Car: " + car.getKey());
            System.out.println("Price: " + car.getValue());
            
            /* Will cause java.util.ConcurrentModificationException */
            carPrice.put("Lamborghini", 300000D);
        }
    }
}

Output
Car: Ferrari
Price: 200000.0
Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
 at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
 at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
 at com.javaquery.collections.map.FailFastExample.main(FailFastExample.java:23)

You can also consider Collection (List, Set, Map) shared between two or more Threads. One is iterating on collection and other tries to add element in it then the thread iterating over it, will throw java.util.ConcurrentModificationException

In interview if you are able to answer this question. They might me interested in checking your knowledge little bit deep. You may face the question How Fail Fast Iterator identifies that the collection is modified?

Fail Safe
It iterate over the clone(copy) of original collection. So It won't throw java.util.ConcurrentModificationException.

Source code (FailSafeExample.java)
/**
 * Example of Fail Safe using ConcurrentHashMap.
 * @author javaQuery
 * @date 4th August, 2016 
 * @Github: https://github.com/javaquery/Examples 
 */
public class FailSafeExample {

    public static void main(String[] args) {
        Map<String, Double> carPrice = new ConcurrentHashMap<String, Double>();
        carPrice.put("Porsche", 100000D);
        carPrice.put("Ferrari", 200000D);

        /* Iterate over Map */
        for (Map.Entry<String, Double> car : carPrice.entrySet()) {
            System.out.println("Car: " + car.getKey());
            System.out.println("Price: " + car.getValue());

            /* Will be added in original copy of Map but won't available in Iterator */
            carPrice.put("Lamborghini", 300000D);
        }
        System.out.println("=== loop finished ===");
        System.out.println("Car: Lamborghini" + ", Price: " + carPrice.get("Lamborghini"));
    }
}

Output
Car: Ferrari
Price: 200000.0
Car: Porsche
Price: 100000.0
=== loop finished ===
Car: Lamborghini, Price: 300000.0

How to Initialize Set in declaration?

Following excerpt show How you can Initialize Set in its declaration.

Source code
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author javaQuery
 * @date 29th October, 2015
 * Initialize Set in its declaration.
 */
public class InitializeSetExample {
    public static void main(String[] args) {
        /* Declare and Initialize Set of Integer */
        Set<Integer> setIntegers = new HashSet<Integer>(Arrays.asList(10, 20, 30));
        
        System.out.println("Print value of Set<Integer>");
        /* Print value of Set */
        for (Integer integer : setIntegers) {
            System.out.println(integer);
        }
        
        /* Declare and Initialize Set of String */
        Set<String> setStrings = new HashSet<>(Arrays.asList("Chirag", "Yogita", "Vicky", "Heer"));
        
        System.out.println("Print value of Set<String>");
        /* Print value of Set */
        for (String string : setStrings) {
            System.out.println(string);
        }
    }
}

Output
Print value of Set<Integer>
20
10
30
Print value of Set<String>
Vicky
Heer
Chirag
Yogita

Reference
How to Initialize List in declaration?

How to Initialize List in declaration?

Following excerpt show How you can Initialize List in its declaration.

Source code
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author javaQuery
 * @date 29th October, 2015 Initialize List in its declaration.
 */
public class InitializeListExample {

    public static void main(String[] args) {
        /* Declare and Initialize List of Integer */
        List<Integer> listIntegers = new ArrayList<Integer>(Arrays.asList(10, 20, 30));

        System.out.println("Print value of List<Integer>");
        /* Print value of List */
        for (Integer integer : listIntegers) {
            System.out.println(integer);
        }

        /* Declare and Initialize List of String */
        List<String> listStrings = new ArrayList<String>(Arrays.asList("Chirag", "Yogita", "Vicky", "Heer"));

        System.out.println("Print value of List<String>");
        /* Print value of List */
        for (String string : listStrings) {
            System.out.println(string);
        }
    }
}

Output
Print value of List<Integer>
10
20
30
Print value of List<String>
Chirag
Yogita
Vicky
Heer

Reference
How to Initialize Set in declaration?

Example of distinct in Java 8

Stream<T> distinct()
Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.

For ordered streams, the selection of distinct elements is stable (for duplicated elements, the element appearing first in the encounter order is preserved.) For unordered streams, no stability guarantees are made.

Source code (Employee.java)
public class Employee {
    private String Email;
    
    public String getEmail() {
        return Email;
    }

    public void setEmail(String Email) {
        this.Email = Email;
    }

    /**
     * You've to Override `equals` and `hashCode` methods in order to work `distinct` method of `stream`.
     */
    @Override
    public boolean equals(Object obj) {
        Employee compareEmployee = (Employee) obj;
        if(this.Email != null && compareEmployee != null){
            return this.Email.equalsIgnoreCase(compareEmployee.getEmail());
        }else{
            return false;
        }
    }

    @Override
    public int hashCode() {
        if(this.Email != null && !this.Email.trim().isEmpty()){
            return this.Email.hashCode();
        }else{
            return -1;
        }
    }    
}

Source code
import java.util.ArrayList;
import java.util.List;

public class DistinctExample {
    public static void main(String[] args) {
        /* Create `List` of `String` and add duplicate records */
        List<String> listStrings = new ArrayList<>(0);
        listStrings.add("Chirag");
        listStrings.add("Vicky");
        listStrings.add("Vicky");
        
        System.out.println("Distinct Strings in `listStrings`: ");
        listStrings.stream()
                   .distinct()
                   .forEach(strName -> {
                       System.out.println("> " + strName);
                   });
        
        /* Create `List` of `Long` and add duplicate records */
        List<Long> listNumbers = new ArrayList<>(0);
        listNumbers.add(22L);
        listNumbers.add(22L);
        listNumbers.add(11L);
        
        System.out.println("Distinct Numbers in `listNumbers`: ");
        listNumbers.stream()
                   .distinct()
                   .forEach(number -> {
                       System.out.println("> " + number);
                   });
        
        /**
         * Create `List` of `Employee` and add duplicate records
         * Note: In case of Bean or Pojo you've to Override `equals` and `hashCode` methods in Bean or Pojo
         */
        List<Employee> listEmployee = new ArrayList<>(0);
        Employee employeeChirag = new Employee();
        employeeChirag.setEmail("chirag.thakor@javaquery.com");
        listEmployee.add(employeeChirag);
        
        Employee employeeVicky = new Employee();
        employeeVicky.setEmail("vicky.thakor@javaquery.com");
        listEmployee.add(employeeVicky);
        
        Employee employeeDuplicate = new Employee();
        employeeDuplicate.setEmail("vicky.thakor@javaquery.com");
        listEmployee.add(employeeDuplicate); 
        
        System.out.println("Distinct Employee in `listEmployee`: ");
        listEmployee.stream()
                    .distinct()
                    .forEach(employee -> {
                       System.out.println("> " + employee.getEmail());
                    });
    }
}

Output
Distinct Strings in `listStrings`: 
> Chirag
> Vicky
Distinct Numbers in `listNumbers`: 
> 22
> 11
Distinct Employee in `listEmployee`: 
> chirag.thakor@javaquery.com
> vicky.thakor@javaquery.com

Example of mapToLong in Java 8


LongStream mapToLong(ToLongFunction<? super T> mapper)
Returns a LongStream consisting of the results of applying the given function to the elements of this stream.

Source code (Company.java)
public class Company {
    private Long id;
    private String CompanyName;
 
 public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCompanyName() {
        return CompanyName;
    }

    public void setCompanyName(String CompanyName) {
        this.CompanyName = CompanyName;
    }
}

Source code
import java.util.ArrayList;
import java.util.List;

public class MapToLongExample {
    public static void main(String[] args) {
        /* Create an object of `Company` and set values */
        Company companyApple = new Company();
        companyApple.setId(1L);
        companyApple.setCompanyName("Apple");
        
        Company companySamsung = new Company();
        companySamsung.setId(2L);
        companySamsung.setCompanyName("Samsung");
       
        /**
         * - Create `List` of `Company`
         * - Add `companyApple` and `companySamsung` to List.
         */
        List<Company> mobileCompanies=  new ArrayList<>();
        mobileCompanies.add(companyApple);
        mobileCompanies.add(companySamsung);
        
        /**
         * JavaDoc: `mapToLong` method
         * Returns a LongStream consisting of the results of applying the given function to the elements of this stream.
         * 
         * Explanation: `.mapToLong(Company::getId)` / `.mapToLong(company -> company.getId())`
         * In this operation we are calling method `getId()` on each object of `Company` in List.
         * That returns the `LongStream` of value(Id) of all object in List.
         * At last print company `Ids`.
         */
        mobileCompanies.stream()
                       .mapToLong(Company::getId)
                       .forEach(companyID ->{
                           System.out.println(companyID);
                       });
    }
}

Explanation: .mapToLong(Company::getId) / .mapToLong(company -> company.getId())
In this operation we are calling method getId() on each object of Company in List. That returns the LongStream of value(Id) of all object in List. At last print company Ids.


Output
1
2
Other References:
Example of mapToDouble in Java 8
Example of mapToInt in Java 8

Example of mapToInt in Java 8


IntStream mapToInt(ToIntFunction<? super T> mapper);
Returns an IntStream consisting of the results of applying the given function to the elements of this stream.

Source code (Item.java)
public class Item {
    private String Name;
    private int Quantity;

    public String getName() {
        return Name;
    }

    public void setName(String Name) {
        this.Name = Name;
    }

    public int getQuantity() {
        return Quantity;
    }

    public void setQuantity(int Quantity) {
        this.Quantity = Quantity;
    }
}

Source code
import java.util.ArrayList;
import java.util.List;

public class MapToIntExample {
    public static void main(String[] args) {
        /* Create an object of `Item` and set values */
        Item itemSamsungGalaxy6 = new Item();
        itemSamsungGalaxy6.setName("Samsung Galaxy 6");
        itemSamsungGalaxy6.setQuantity(20);
        
        Item itemNexus = new Item();
        itemNexus.setName("Nexus 5");
        itemNexus.setQuantity(12);
        
        /**
         * - Create `List` of `Item`
         * - Add `itemSamsungGalaxy6` and `itemNexus` to List.
         */
        List<Item> listItems = new ArrayList<>();
        listItems.add(itemSamsungGalaxy6);
        listItems.add(itemNexus);
        
        /**
         * JavaDoc: `mapToInt` method
         * Returns an IntStream consisting of the results of applying the given function to the elements of this stream.
         * 
         * Explanation: `.mapToInt(Item::getQuantity)` / `.mapToInt(item -> item.getQuantity())`
         * In this operation we are calling method `getQuantity()` on each object of `Item` in List.
         * That returns the `IntStream` of value(Quantity) of all object in List.
         * And we are doing summation of all quantity
         */
        int totalQuantity = listItems.stream()
                                     .mapToInt(Item::getQuantity)
                                     .sum();
        
        /* Print the total quantity */
        System.out.println("Total Quantity: " + totalQuantity);
    }
}

Explanation: .mapToInt(Item::getQuantity) / .mapToInt(item -> item.getQuantity())
In this operation we are calling method getQuantity() on each object of Item in List. That returns the IntStream of value(Quantity) of all object in List. And we are doing summation of all quantity


Output
Total Quantity: 32
Other References:
Example of mapToDouble in Java 8