import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.function.Supplier;
import java.util.function.Function;

/**
 * {@link <a href=
 * "https://[Log in to view URL]"
 * target= "_blank"></a>}
 * 
 * @author itammb ( Italia Massimiliano Buscati )
 * @version JDK 1.15
 *
 */
class Main {
	private final static class Student {
		private String subject, name, surname, city;
		private int age;

		public String getSubject() {
			return subject;
		}

		public String getName() {
			return name;
		}

		public String getCity() {
			return city;
		}

		public int getAge() {
			return age;
		}

		@Override
		public String toString() {
			return "Student [subject=" + subject + ", name=" + name + ", surname=" + surname + ", city=" + city
					+ ", age=" + age + "]";
		}

		public Student(String subject, String name, String surname, String city, int age) {
			this.subject = subject;
			this.name = name;
			this.surname = surname;
			this.city = city;
			this.age = age;
		}
	}

	private static class UniTest {

		/**
		 * @see Stream#collect(java.util.function.Supplier,
		 *      java.util.function.BiConsumer, java.util.function.BiConsumer)
		 *      {@link Supplier BiConsumer}
		 */
		public void combinator_accumulator(List<Student> source) {

			// R result = supplier.get();
			// for (T element : this stream)
			// accumulator.accept(result, element);
			// return result;

			List<Student> students = source.stream().collect(
					// fornitore
					() -> new ArrayList<>(),
					// accumulatore [List<Student>, Student]
					(accumulatore, newItemFromStream) -> {
						accumulatore.add(newItemFromStream);
						// System.out.println( "accumulatore -> " + accumulatore );
					},
					// combinatore di due accumulatori
					ArrayList::addAll);

			students.forEach((student) -> System.out.println(student.toString()));
		}

		/**
		 * @see Stream#collect(java.util.stream.Collector)
		 *      {@link Collectors#groupingBy(java.util.function.Function) }
		 */
		public void groupingBy(List<Student> source, Function<? super Student, ? extends String> bySubject) {
			Map<String, List<Student>> studentsBySubject = source.stream().collect(Collectors.groupingBy(bySubject));

			studentsBySubject.entrySet().stream().forEach((student) -> System.out.println(student.toString()));
		}

		/**
		 * @see Stream#parallel()
		 * @see Stream#unordered()
		 *      {@link Collectors#groupingByConcurrent(java.util.function.Function) }
		 */
		public void groupingBy_concurrent(List<Student> source, Function<? super Student, ? extends String> bySubject) {
			// concorrenza - è possibile se l'ordine non è importante
			Map<String, List<Student>> studentsBySubject = source.stream().parallel().unordered()
					.collect(Collectors.groupingByConcurrent(bySubject));

			studentsBySubject.forEach(
					(subject, registry) -> System.out.println(subject + "\r\n" + Arrays.toString(registry.toArray())));
		}

		/**
		 * @see Collectors#mapping(Function, java.util.stream.Collector)
		 * 
		 */
		public void sub_groupingBy(List<Student> source, Function<? super Student, ? extends String> byCity,
				Function<? super Student, ? extends String> mapper) {
			Map<String, List<String>> studentsByCity = source.stream()
					.collect(Collectors.groupingBy(byCity, Collectors.mapping(mapper, Collectors.toList())));

			System.out.println(studentsByCity);

		}

		/**
		 * @see Collectors#groupingBy(Function, Supplier, java.util.stream.Collector)
		 * 
		 */
		public void sub_groupingBy_order(List<Student> source, Function<? super Student, ? extends String> byCity,
				Function<? super Student, ? extends String> mapper) {

			Map<String, List<String>> orderByCity = source.stream().collect(
					Collectors.groupingBy(byCity, TreeMap::new, Collectors.mapping(mapper, Collectors.toList())));

			System.out.println(orderByCity);
		}

		public void sub_groupingBy_count(List<Student> source, Function<? super Student, ? extends Integer> byAge) {

			Map<Integer, Long> countByAge = source.stream()
					.collect(Collectors.groupingBy(byAge, Collectors.counting()));

			System.out.println(countByAge);
		}

		public static List<Student> createTest() {
			// elementi in serie
			return Arrays.asList(new Student("Math", "John", "Smith", "Miami", 19),
					new Student("Programming", "Mike", "Miles", "New York", 21),
					new Student("Math", "Michael", "Peterson", "New York", 20),
					new Student("Math", "James", "Robertson", "Miami", 20),
					new Student("Programming", "Kyle", "Miller", "Miami", 20));

		};
	}

	public static void main(String args[]) {
		// Unit test - accumulatore
		new UniTest().combinator_accumulator(UniTest.createTest());

		// Unit test - classificazione
		new UniTest().groupingBy(UniTest.createTest(), Student::getSubject);

		// Unit test - classificazione concorrente
		new UniTest().groupingBy_concurrent(UniTest.createTest(), Student::getSubject);

		// Unit test - sotto classificazione NON ORDINATA
		new UniTest().sub_groupingBy(UniTest.createTest(), Student::getCity, Student::getName);

		// Unit test - sotto classificazione ORDINATA
		new UniTest().sub_groupingBy_order(UniTest.createTest(), Student::getCity, Student::getName);

		// Unit test - sotto classificazione COUNT
		new UniTest().sub_groupingBy_count(UniTest.createTest(), Student::getAge);
	}
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: