The operation 'map' applies the SAME OPERATION to EACH ELEMENT of the stream. Afterwards, the stream is formed from the results of the operations - 'map' can therefore change the type of the stream elements. The operations 'mapToInt' and 'mapToDouble' are special versions of the map operation. For example, if we had a list of 'Teacher' objects and wanted to count the number of teachers whose name is longer than 10 characters, we could use a stream as follows: // count returns a value of type long long count = teachers.stream().map(teacher -> teacher.getName()). filter(name -> name.length() > 10).count(); Another useful stream operation is 'collect'. It allows you to 'FORM A COLLECTION FROM A STREAM' again. So if we have a list of Teacher objects following the previous example, and we want to create a list of the teachers' email addresses, we can do so by combining the operations 'map' and 'collect': ArrayList emails = teachers.stream().map(teacher -> teacher.getEmail()). collect(Collectors.toCollection(ArrayList::new)); Another example where we have a list of integers. We want to create a new list that has only the negative elements from the original list. Since the 'collect' operation only works on object type streams, we change the stream from 'int' type to 'Integer' type with the boxed() operation before converting to a list: ArrayList negatives = numbers.stream().mapToInt(number -> number). filter(number -> number < 0).boxed(). collect(Collectors.toCollection(ArrayList::new)); Let's look at another example where we want to create a new list that only includes those 'Student' objects with less than 30 credits: ArrayList lessThan30 = students.stream(). filter(student -> student.getCredits() < 30). collect(Collectors.toCollection(ArrayList::new));