Immutable collection
- Create an immutable collection: data cannot be modified and defensively copied to the immutable collection; safe when called by an untrusted library.
- There are static methods of in the List Set Map interface->Get an immutable collection–>Cannot add, delete, modify (read-only)
List<String> list = List.of("","",""); //remove add set xxx is not allowed Set<String> set = Set.of("","","");//No index //Get an immutable set collection. Parameters ensure uniqueness. Map<String,String> map = Map.of("key","value"); //Keys cannot be repeated. Parameters have an upper limit (10) //When there are 10 more parameters ->ofEntries jdk10->copyOf ------------Fang Yi--------------- HashMap<String,String> map = new HashMap<>(); map.put("123","123");//put more than ten //Get all key value objects Entry objects Set<Map.Entry<String,String>>entries = map.entrySet(); //Convert entries into an array. The type is entry object. //toArray method compares the length of the collection with the length of the array //Set length > Array length Create a new array based on the actual number of collection data, otherwise <= use it directly and the excess is nul Map.Entry[] arr = entires.toArray(new Map.Entry[0]); Map map1 = Map.ofEntries(arr); //Immutable creation completed ---------------Fang 2------------------ //simplify Map<Object,Object> map1 = Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])); ---------------Fang San------------------ //jdk10 Map<String,String> map1 = mapMap.copyOf(map);
Stream
Introduction
Combined with Lambda expressions to simplify collection and array operations
characteristic:
Stream itself does not store elements.
Stream does not change the source object. Instead, they return a new Stream holding the result.
Stream operations are performed lazily. This means they wait until the results are needed. That is, once the termination operation is performed, the intermediate operation chain is executed and the results are generated.
Once a Stream performs a termination operation, it cannot call other intermediate operations or termination operations.
Streaming
eg:
For example, you want to filter out all even numbers from a collection containing integers and encapsulate them into a new List to return
List<Integer> evens = new ArrayList<>(); for (final Integer num : nums) { if (num % 2 == 0) { evens.add(num); } }
Through Java8’s streaming processing, the code is simplified to:
List<Integer> evens = nums.stream().filter(num -> num % 2 == 0).collect(Collectors.toList()); ------eg2-------- ArrayList<String> list = new ArrayList<>(); list.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3 ).forEach(name -> System.out.println(name ));
Explanation: The stream()
operation converts the collection into a stream. filter()
performs our custom filtering process. Here, all even numbers are filtered out through lambda expressions. Finally We use collect()
to encapsulate the result, and use Collectors.toList()
to specify its encapsulation and return it as a List collection.
A stream processing can be divided into three parts: conversion into streams, intermediate operations, and terminal operations
Take collections as an example. For a streaming operation, we first need to call the
stream()
function to convert it into a stream, and then call the correspondingintermediate operation
to achieve what we need. Collection operations, such as filtering, conversion, etc., and finally encapsulates the previous results throughTerminal operations
and returns the form we need.
step:
-
Get stream exile data
Getting method Method name Description Single column collection default Stream stream() Default method in Collection Dual column collection None (turn keySet or entrySet into a single column first) Cannot use stream directly Array public static Stream stream (T[] array) Static method in Arrays tool class A bunch of scattered data td>
public static Stream of (T…values) Static methods in the Stream interface Single column collection:
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a","b","c","d","e","f"); //Get a pipeline and put the collection data on the pipeline /*Stream<String> stream = list.stream(); stream.forEach(new Consumer<String>() { @Override public void accept(String s) { // s represents each data on the pipeline at a time System.out.println(s); } });*/ list.stream().forEach(s-> System.out.println(s));
Two-column collection:
//Create a two-column collection HashMap<String, Integer> hm = new HashMap<>(); hm.put("aaa",1111); hm.put("bbb",2222); hm.put("ccc",3333); hm.put("mmm",4444); //Get stream stream //Print all keys hm.keySet().stream().forEach(s-> System.out.println(s)); //Print all key-value pairs hm.entrySet().stream().forEach(s-> System.out.println(s));
Array:
//Create array int[] arr = {1,2,3,4,5,6,7}; Arrays.stream(arr).forEach(s-> System.out.println(s));
Scattered data:
Stream.of(1,2,3,4).forEach(s-> System.out.println(s));
be careful:
Stream.of can be used for reference data type arrays but not for basic data types.
-
Leverage in-stream API operations
Filter Transform -> Intermediate method (you can continue to call other methods later)
Statistics Print -> Termination method (no other calls can be made later)
Intermediate operations
Filtering and slicing
filter ->Filter
limit -> get the first few elements
skip -> skip the first few elements
distinct -> element deduplication dependency (hashCode and equals methods)
concat -> merge the two streams a and b into one stream (parent class)
filter
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a123","b123","c222","d11","e22","f11"); //filter // list.stream().filter(new Predicate<String>() { // @Override // public boolean test(String s) { // //The return value is true, leave false and discard it // return s.startsWith("a"); // } // }).forEach(s-> System.out.println(s)); list.stream().filter(s->s.startsWith("a")).forEach(s-> System.out.println(s));
limit/skip
//Get the first three list.stream().limit(3).forEach(s-> System.out.println(s)); //Skip the first 4 list.stream().skip(4).forEach(s-> System.out.println(s));
distinct
list.stream().distinct().forEach(s-> System.out.println(s));
concat
Stream.concat(list.stream(),list2.stream()).forEach(s-> System.out.println(s));
Mapping
map -> Convert the data type in the stream. Receive a function as a parameter. The function will be applied to each element and map it into a new element.
flatMap -> receives a function as a parameter, replaces each value in the stream with another stream, and then connects all streams into one stream
mapToDouble -> generates a new DoubleStream
mapToInt -> generate a new IntStream
mapToLong -> generates a new LongStream.
Note: Does not affect the original data
map
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a123-15","b123-56","a123-22","d11-25","e22-525","f11- 59"); //Only get the inner -post data String ->int // The first type: the original type of the data in the stream. The second type: the type to be converted. //apply formal parameter s: data in the stream //Return value converted data //After the map method is executed, the data on the stream becomes an integer. // list.stream().map(new Function<String, Integer>() { // @Override // public Integer apply(String s) { // String[] arr = s.split("-"); // String ageString = arr[1]; // int age = Integer.parseInt(ageString); // return age; // } // }).forEach(s-> System.out.println(s)); list.stream().map(s-> Integer.parseInt(s.split("-")[1])).forEach(s-> System.out.println(s)); ? ? ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a123-male-15","b123-male-56","a123-female-22","d11-female-25","e22- Female-525","f11-Female-59"); //Get names whose length is greater than 3 //Get the name first List<String> collect = list.stream().map(e -> e.split("-")[0]).filter(s -> s.length() > 3).collect(Collectors. toList()); List<String> collect = list.stream().map(Employee::getName).filter(s -> s.length() > 3).collect(Collectors.toList());
//Suppose you want to filter out the names of all students majoring in computer science. Based on the filter filter, you can map the student entities into student name strings through map. List<String> names = students.stream() .filter(student -> "Computer Science".equals(student.getMajor())) .map(Student::getName).collect(Collectors.toList()); //Want to calculate the sum of the ages of all students majoring in computer science int totalAge = students.stream() .filter(student -> "Computer Science".equals(student.getMajor())) .mapToInt(Student::getAge).sum();
flatMap
flatMap converts each value in a stream into streams, and then flattens these streams into a stream within a stream.
//Output all non-repeating characters that make up this array String[] strs = {"java8", "is", "easy", "to", "use"}; List<String[]> distinctStrs = Arrays.stream(strs) .map(str -> str.split("")) // Map to Stream<String[]> .distinct() .collect(Collectors.toList()); /* [j, a, v, a, 8] [i, s] [e, a, s, y] [t,o] [u, s, e] */ List<String> distinctStrs = Arrays.stream(strs) .map(str -> str.split("")) // Map to Stream<String[]> .flatMap(Arrays::stream) // Flatten to Stream<String> .distinct() .collect(Collectors.toList()); //books->list Book book = writers.stream().flatMap(writer -> writer.getBooks().stream()) .max(new BookComparator()).get();
merge, cross, difference
List<String> A = new ArrayList<>(); Collections.addAll(A,"1","2","3","4"); List<String> B = new ArrayList<>(); Collections.addAll(A,"3","4","5","6","7"); ? //Union A.addAll(B); List<String> AuB = A.stream().distinct().collect(Collectors.toList()); System.out.println("Union:" + AuB); //[1, 2, 3, 4, 5, 6, 7] ? //Intersection B::contains = s -> B.contains(s) Higher versions of IDEA will prompt for conversion List<String> AnB = A.stream().filter(B::contains).collect(Collectors.toList()); System.out.println("Intersection:" + AnB); //[3, 4] ? //Difference set List<String> difference = A.stream().filter(s -> !B.contains(s)).collect(Collectors.toList()); System.out.println("The complement of B in A:" + difference);
Sort
sorted() -> natural sorting ascending order
sorted(Comparator com) -> Sort by comparator order
//Ascending order //1.Natural sorting list = list.stream().sorted().collect(Collectors.toList()); //2.Comparator sorts according to age list = list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList()); ? //descending order //1. Natural sorting uses the reverseOrder() method provided by Comparator list = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()); //2.Comparator sorts according to age list = list.stream().sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList()); ? ? //Multi-field sorting //First sort by name in ascending order, if the names are the same then order by age in ascending order list = list.stream().sorted(Comparator.comparing(Student::getName).thenComparing(Student::getAge)).collect(Collectors.toList());
Match
match is used for matching operations, and its return value is a boolean
type. Through match
, you can easily verify whether a certain type of element exists in a list
.
// Verify whether there is a string starting with a in the list. If the first one is matched, true will be returned. boolean anyStartsWithA = stringCollection .stream() .anyMatch((s) -> s.startsWith("a")); ? System.out.println(anyStartsWithA); // true ? // Verify whether the strings in the list all start with a boolean allStartsWithA = stringCollection .stream() .allMatch((s) -> s.startsWith("a")); ? System.out.println(allStartsWithA); // false ? // Verify whether the strings in the list do not start with z, boolean noneStartsWithZ = stringCollection .stream() .noneMatch((s) -> s.startsWith("z")); ? System.out.println(noneStartsWithZ); // true
Termination method
forEach -> traverse
(long)count -> statistics
Reduce -> Protocol
toArray() -> Collect data from the stream and put it into an array
collect (Collector collector) -> collect data in the stream and put it into the collection
Count
count
is a terminal operation that can count the total number of elements in the stream
stream. The return value is of type long
// First filter the strings starting with b in the list, and then count the number long startsWithB = stringCollection .stream() .filter((s) -> s.startsWith("b")) .count(); System.out.println(startsWithB); // 3
Reduce
Reduce
Chinese translation is: reduce, shrink. By taking the parameter Function
, list
can be reduced to a value. Its return type is of type Optional
.
Optional<String> reduced = stringCollection .stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); // "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2" BigDecimal subjectTotalIncomeBudget = entry.getValue().stream() .map(PmJtProjectSaleContractPrice::getTotalAmountExcludeTax).reduce(BigDecimal.ZERO,BigDecimal::add); //BigDecimal.ZERO: This represents the initial value. When performing a reduce operation, the value used for the first time is the initial value. Here, BigDecimal.ZERO means the initial value is 0. //BigDecimal::add: This represents a BinaryOperator, which represents how to combine two elements. Here, the add method of the BigDecimal class is used, which means adding two BigDecimals.
collect
//toArray() ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a123-15","b123-56","a123-22","d11-25","e22-525","f11- 59"); System.out.println(Arrays.toString(list.stream().toArray())); // String[] arr = list.stream().toArray(new IntFunction<String[]>() { // @Override // public String[] apply(int value) { // return new String[value]; // } // }); System.out.println(Arrays.toString(list.stream().toArray(value->new String[value])));
collect (Collector collector) -> Collect data in the stream and put it into a collection (List Set Map)
ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a123-male-15","b123-male-56","a123-female-22","d11-female-25","e22- Female-525","f11-Female-59"); //Collect men list.stream() .filter(s -> "male".equals(s.split("-")[1])) //.collect(Collectors.toList()); Collect into List collection without deduplication //.collect(Collectors.toSet()); Collect into Set and remove duplicates -------------------------------------------------- ---------- ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a123-male-15","b123-male-56","a123-female-22","d11-female-25","e22- Female-525","f11-Female-59"); //Collect key values into map //Note: keys cannot be repeated //Collect men Key: Name Value: Age /*list.stream() .filter(s -> "male".equals(s.split("-")[1])) *//* toMap: Key rules Value rules Key rules: Function generic (type of each data in the stream, type of key in the map collection) -> Generate key Return key Value rules: Function generic (type of each data in the stream, type of value in the map collection) -> Generate value Return value *//* .collect(Collectors.toMap(new Function<String, String>() { @Override public String apply(String s) { //generate key return s.split("-")[0]; } }, new Function<String, Integer>() { @Override public Integer apply(String s) { return Integer.parseInt(s.split("-")[2]); } }));*/ list.stream() .filter(s -> "male".equals(s.split("-")[1])) .collect(Collectors.toMap(s->s.split("-")[0],s->Integer.parseInt(s.split("-")[2])));</ pre> <h3>Example</h3> <pre>//List<List<FieldAttributeDto>> tableValue is sorted (in ascending order) according to the value (string) of FieldName="records_projectStage" in FieldAttributeDto //flatMap error occurs during stages 1-11 List<FieldAttributeDto> flattenedSortedTableValue = tableValue.stream() .flatMap(List::stream) // Flatten a nested list into a stream of single elements .filter(dto -> "records_projectStage".equals(dto.getFieldName())) // Filter out FieldAttributeDto that meets the conditions .sorted(Comparator.comparing(FieldAttributeDto::getLabelValue)) // Sort the qualified FieldAttributeDto .collect(Collectors.toList()); // The collection result is a list //Solve the limitation "stage" begins List<FieldAttributeDto> flattenedSortedTableValue = tableValue.stream() .flatMap(List::stream) // Flatten a nested list into a stream of single elements .filter(dto -> "records_projectStage".equals(dto.getFieldName())) // Filter out FieldAttributeDto that meets the conditions .sorted(Comparator.comparing(this::parseStage)) .collect(Collectors.toList()); // The collection result is a list // Custom method to parse the stage string into an integer private int parseStage(FieldAttributeDto dto) { String stage = dto.getLabelValue(); if (stage.startsWith("stage")) { return Integer.parseInt(stage.substring(2)); } return 0; //Default value } List<List<FieldAttributeDto>> sortedTableValue = tableValue.stream() .map(list -> list.stream() .filter(dto -> dto.getFieldName().equals("records_projectStage")) .findFirst() .orElse(null)) .filter(dto -> dto != null) .sorted(Comparator.comparing(FieldAttributeDto::getValue)) .map(dto -> tableValue.stream() .filter(list -> list.contains(dto)) .findFirst() .orElse(null)) .filter(list -> list != null) .collect(Collectors.toList());