Lambda Optional Checking value presence and conditional action
SysUser user = new SysUser ();SysDept dept = new SysDept ();dept.setDeptName("development" ); user.setDept(dept); Optional<String> optional = Optional.ofNullable(user) .map(SysUser::getDept) .map(SysDept::getDeptName); optional.ifPresent(System.out::println); String deptName = optional.orElse("default" );String deptName = optional.orElseGet(() -> "to get default" );optional.orElseThrow(() -> new RuntimeException ("to throw exception" )); String deptName = Optional.ofNullable(user) .map(SysUser::getDept) .map(SysDept::getDeptName) .orElse("defaultDept" );
Stream Create Streams
Using collection
Create a stream from specified values
Stream.of(T…t)
Stream<Integer> stream = Stream.of(1 , 2 , 3 , 4 , 5 );
Create a stream from an array
Arrays.stream(arr); Arrays.stream(arr, from, to) Stream.of(arr);
Create an empty stream using Stream.empty()
The empty() method is used upon creation to avoid returning null for streams with no element.
Stream<String> streamOfArray = Stream.empty();
Using Stream.builder()
Stream.Builder<String> builder = Stream.builder(); Stream<String> stream = builder.add("a" ).add("b" ).add("c" ).build();
Create an infinite Stream using Stream.iterate()
Stream.iterate(seedValue, (Integer n) -> n * n) .limit(limitTerms) .forEach(System.out::println);
Create an infinite Stream using Stream.generate()
Stream.generate(Math::random) .limit(limitTerms) .forEach(System.out::println);
Create stream from Iterator
Iterator<String> iterator = Arrays.asList("a" , "b" , "c" ).iterator(); Spliterator<T> spitr = Spliterators.spliteratorUnknownSize(iterator, Spliterator.NONNULL); Stream<T> stream = StreamSupport.stream(spitr, false );
Create stream from Iterable
Iterable<String> iterable = Arrays.asList("a" , "b" , "c" ); Stream<T> stream = StreamSupport.stream(iterable.spliterator(), false );
Collect streams List<Integer> numList = Stream.of(1 , 2 , 3 ).toList(); System.out.println(numList);
List<Integer> numList = Stream.of(1 , 2 , 3 ).collect(Collectors.toList()); System.out.println(numList);
Print streams Stream.of(1 , 2 , 3 ).forEach(System.out::println);
Collections Construction Collection Element Type Conversion String list to Object list
by assignment
String[] stringArray = new String [10 ]; Object[] objectArray = stringArray;
by contructor
List<String> stringList = new ArrayList <>(); List<Object> objectList = new ArrayList <>(stringList); Set<String> stringSet = new HashSet <>(); Set<Object> objectSet = new HashSet <>(stringSet);
by for loop
Map<String, List<String>> multiStringValueMap = new HashMap <>(); multiStringValueMap.put("key1" , Arrays.asList("taogen" , "taogen2" )); multiStringValueMap.put(null , Arrays.asList(null , null , null )); multiStringValueMap.put("testNullValue" , null ); Map<String, List<Object>> multiObjectValueMap = new HashMap <>(); multiStringValueMap.forEach((key, value) -> { List<Object> objectList = null ; if (value != null ) { objectList = value.stream() .collect(Collectors.toList()); } multiObjectValueMap.put(key, objectList); }); System.out.println(multiObjectValueMap);
Object list to String list
by Java Stream
List<Object> objectList = new ArrayList <>(); List<String> stringList = objectList.stream() .map(object -> Objects.toString(object, null )) .collect(Collectors.toList()); for (Object s : objectList) { System.out.println(s + ", isNull: " + Objects.isNull(s)); }
by for loop
List<Object> objectList = new ArrayList <>(); List<String> stringList = new ArrayList <>(objectList.size()); for (Object object : objectList) { stringList.add(Objects.toString(object, null )); } for (Object s : objectList) { System.out.println(s + ", isNull: " + Objects.isNull(s)); }
Map<String, List<Object>> multiObjectValueMap = new HashMap <>(); multiObjectValueMap.put("key1" , Arrays.asList(1 , 2 , 3 )); multiObjectValueMap.put(null , Arrays.asList(null , null , null )); multiObjectValueMap.put("testNullValue" , null ); multiObjectValueMap.put("key2" , Arrays.asList("taogen" , "taogen2" )); Map<String, List<String>> multiStringValueMap = new HashMap <>(); multiObjectValueMap.forEach((key, value) -> { List<String> stringList = null ; if (value != null ) { stringList = value.stream() .map(object -> Objects.toString(object, null )) .collect(Collectors.toList()); } multiStringValueMap.put(key, stringList); }); System.out.println(multiStringValueMap);
Warning: to convert a object value to a string value you can use Objects.toString(object) or object != null ? object.toString() : null. but not String.valueOf() and toString(). The result of String.valueOf(null) is “null” not null. If the object value is null, calling toString() will occur NullPointerExcpetion.
Collection Conversion To Array
Object list to array
User[] users = userList.toArray(new User [0 ]); Integer[] integers = integerList.toArray(new Integer [0 ]); String[] strings = stringList.toArray(new String [0 ]);
User[] users = userList.stream().toArray(User[]::new ); Integer[] integers = integerList.stream().toArray(Integer[]::new ); String[] strings = stringList.stream().toArray(String[]::new ); String[] strings = stringList.toArray(String[]::new );
int [] array = new int [list.size()];for (int i = 0 ; i < list.size(); i++) array[i] = list.get(i);
To ArrayList
Convert Set to ArrayList
Set<String> set = new HashSet (); ArrayList<String> list = new ArrayList (set);
List<String> list = set.stream().collect(Collectors.toList());
var list = List.copyOf(set);
Convert Wrapper Type Array to ArrayList
String[] array = new String [10 ]; Integer[] array2 = new Integer [10 ]; ArrayList<String> list = new ArrayList (Arrays.asList(array));
Convert Primitive Array to ArrayList
int [] input = new int []{1 ,2 ,3 ,4 };List<Integer> output = Arrays.stream(input).boxed().collect(Collectors.toList());
int [] input = new int []{1 ,2 ,3 ,4 };List<Integer> output = IntStream.of(input).boxed().collect(Collectors.toList());
To Set
Convert ArrayList to Set
ArrayList<String> list = new ArrayList (); Set<String> set = new HashSet (list);
Set<String> set = list.stream().collect(Collectors.toSet());
var set = Set.copyOf(list);
Convert Wrapper Type Array to Set
String[] array = new String [10 ]; Set<String> set = new HashSet (Arrays.asList(array));
Convert other set classes
list.stream().collect(Collectors.toCollection(LinkedHashSet::new ))
To Map
Convert Object Fields of List to Map
List<SysUser> sysUserList = getUserList(); Map<Long, String> idToName = sysUserList.stream() .collect(Collectors.toMap(SysUser::getId, SysUser::getName)); Map<Long, String> idToName = sysUserList.stream() .collect(Collectors.toMap(item -> item.getId(), item -> item.getName()));
List<IdName> list = getIdNameList(); Map<Long, IdName> idToObjMap = list.stream() .collect(Collectors.toMap(IdName::getId, Function.identity())); Map<Long, IdName> idToObjMap = list.stream() .collect(Collectors.toMap(item -> item.getId(), item -> item));
Convert to other map classes
List<IdName> idNameList = new ArrayList <>(); Map<Integer,String> idToNameMap = idNameList.stream().collect(Collectors.toMap(IdName::getId, IdName::getName, (o1, o2) -> o1, TreeMap::new ));
List<IdName> idNameList = new ArrayList <>(); idNameList.stream().collect(Collectors.toConcurrentMap(IdName::getId, IdName::getName));
Merge Merge byte[] array
use System.arraycopy
byte [] one = getBytesForOne();byte [] two = getBytesForTwo();byte [] combined = new byte [one.length + two.length];System.arraycopy(one,0 ,combined,0 ,one.length); System.arraycopy(two,0 ,combined,one.length,two.length);
Use List
byte [] one = getBytesForOne();byte [] two = getBytesForTwo();List<Byte> list = new ArrayList <Byte>(Arrays.<Byte>asList(one)); list.addAll(Arrays.<Byte>asList(two)); byte [] combined = list.toArray(new byte [list.size()]);
Use ByteBuffer
byte [] allByteArray = new byte [one.length + two.length + three.length];ByteBuffer buff = ByteBuffer.wrap(allByteArray);buff.put(one); buff.put(two); buff.put(three); byte [] combined = buff.array();
Convert List to Tree convert list to tree with parentId
The data
[ { id: 1 , name: "a" , prarentId: 0 } , { id: 10 , name: "b" , prarentId: 1 } , { id: 2 , name: "c" , prarentId: 0 } ]
The process of conversion
1. original list a b c 2. link children and mark first level nodes *a -> b b *c 3. get first level nodes a -> b c
Implementation
@Data public class IdName { private String id; private String name; private String parentId; private List<IdName> children; public IdName (String id, String name, String parentId) { this .id = id; this .name = name; this .parentId = parentId; } private void putChildren (IdName idName) { if (this .children == null ) { this .children = new ArrayList <>(); } this .children.add(idName); } public static List<IdName> convertListToTree (List<IdName> list) { if (list == null || list.isEmpty()) { return Collections.emptyList(); } Map<String, IdName> map = list.stream() .collect(Collectors.toMap(IdName::getId, Function.identity())); List<IdName> firstLevelNodeList = new ArrayList <>(); for (IdName idName : list) { IdName parent = map.get(String.valueOf(idName.getParentId())); if (parent != null ) { parent.putChildren(idName); } else { firstLevelNodeList.add(idName); } } return firstLevelNodeList; } } public static void main (String[] args) { List<IdName> idNames = new ArrayList <>(); idNames.add(new IdName ("1" , "Jack" , "0" )); idNames.add(new IdName ("2" , "Tom" , "0" )); idNames.add(new IdName ("3" , "Jerry" , "1" )); System.out.println(IdName.convertListToTree(idNames)); }
Multiple level data is in multiple tables
public List<AreaVo> getAreaVoList () { List<Province> provinces = iProvinceService.list( new LambdaQueryWrapper <Province>() .select(Province::getId, Province::getName, Province::getCode)); List<City> cities = iCityService.list( new LambdaQueryWrapper <City>() .select(City::getId, City::getName, City::getCode, City::getProvinceCode)); List<County> counties = iCountyService.list( new LambdaQueryWrapper <County>() .select(County::getId, County::getName, County::getCode, County::getCityCode)); List<AreaVo> resultList = new ArrayList <>(); resultList.addAll(AreaVo.fromProvince(provinces)); resultList.addAll(AreaVo.fromCity(cities)); resultList.addAll(AreaVo.fromCounty(counties)); return AreaVo.convertListToTree(resultList); } public class AreaVo { private String label; private String value; private String parentId; private List<AreaVo> children; public static List<AreaVo> fromProvince (List<Province> provinces) { if (provinces == null || provinces.isEmpty()) { return Collections.emptyList(); } return provinces.stream() .map(item -> new AreaVo (item.getName(), item.getCode(), "0" )) .sorted(Comparator.comparing(AreaVo::getValue)) .collect(Collectors.toList()); } public static List<AreaVo> convertListToTree (List<AreaVo> list) {} }
Find Path of Node In a Tree private void setAreaForList (List<User> records) { List<String> areaCodeList = records.stream() .map(User::getAreaId) .filter(Objects::nonNull) .map(String::valueOf) .collect(Collectors.toList()); List<AreaItem> areaItemList = iAreaService.findSelfAndAncestors(areaCodeList); if (areaItemList == null || areaItemList.isEmpty()) { return ; } Map<String, AreaItem> areaItemMap = areaItemList.stream() .collect(Collectors.toMap(AreaItem::getCode, Function.identity())); records.stream() .filter(entity -> entity.getAreaId() != null ) .forEach(entity -> { List<AreaItem> areaPath = new ArrayList <>(); String areaCode = entity.getAreaId().toString(); String tempCode = areaCode; AreaItem areaItem = null ; while ((areaItem = areaItemMap.get(tempCode)) != null ) { areaPath.add(0 , areaItem); tempCode = areaItem.getParentCode(); } if (CollectionUtils.isEmpty(areaPath)) { return ; } int totalLevel = 2 ; if (areaPath.size() < totalLevel) { int supplementSize = totalLevel - areaPath.size(); for (int i = 0 ; i < supplementSize; i++) { areaPath.add(null ); } } else { areaPath = areaPath.subList(0 , totalLevel); } entity.setAreaPath(areaPath); entity.setAreaArray(areaPath.stream() .map(areaPathItem -> areaPathItem == null ? null : areaPathItem.getCode()) .collect(Collectors.toList())); }); }
Multiple level data is in multiple tables
public List<AreaItem> findSelfAndAncestors (List<String> areaCodeList) { if (CollectionUtils.isEmpty(areaCodeList)) { return Collections.emptyList(); } List<String> tempCodeList = areaCodeList; List<AreaItem> resultAreaList = new ArrayList <>(); List<AreaCounty> countyList = iAreaCountyService.list( new LambdaQueryWrapper <AreaCounty>() .select(AreaCounty::getCode, AreaCounty::getName, AreaCounty::getCityCode) .in(AreaCounty::getCode, tempCodeList)); if (!CollectionUtils.isEmpty(countyList)) { AreaItem.fromAreaCounty(countyList) .forEach(areaItem -> { resultAreaList.add(areaItem); areaItem.setLevel(3 ); }); tempCodeList = areaCodeList; tempCodeList.addAll(countyList.stream() .map(AreaCounty::getCityCode) .collect(Collectors.toList())); } List<AreaCity> cityList = iAreaCityService.list( new LambdaQueryWrapper <AreaCity>() .select(AreaCity::getCode, AreaCity::getName, AreaCity::getProvinceCode) .in(AreaCity::getCode, tempCodeList)); if (!CollectionUtils.isEmpty(cityList)) { AreaItem.fromAreaCity(cityList) .forEach(areaItem -> { resultAreaList.add(areaItem); areaItem.setLevel(2 ); }); tempCodeList = areaCodeList; tempCodeList.addAll(cityList.stream() .map(AreaCity::getProvinceCode) .collect(Collectors.toList())); } List<AreaProvince> provinceList = iAreaProvinceService.list( new LambdaQueryWrapper <AreaProvince>() .select(AreaProvince::getCode, AreaProvince::getName) .in(AreaProvince::getCode, tempCodeList)); if (!CollectionUtils.isEmpty(provinceList)) { AreaItem.fromAreaProvince(provinceList) .forEach(areaItem -> { resultAreaList.add(areaItem); areaItem.setLevel(1 ); }); } return resultAreaList; }
Find Descendant Nodes in a Tree Find self and descendant list
private List<User> findSelfAndDescendants (Integer parentId) { List<User> resultList = new ArrayList <>(); List<Integer> tempIds = new ArrayList <>(); tempIds.add(parentId); List<User> descendants = null ; while (!CollectionUtils.isEmpty(descendants = getListByIds(tempIds))) { resultList.addAll(descendants); tempIds.clear(); tempIds = descendants.stream().map(User::getId).collect(Collectors.toList()); } return resultList; } public List<User> getListByIds (List<Integer> ids) {}
Find descendant list
private List<User> findDescendants (Integer parentId) { List<User> resultList = new ArrayList <>(); List<Integer> tempIds = new ArrayList <>(); tempIds.add(parentId); List<User> descendants = null ; while (!CollectionUtils.isEmpty(descendants = getListByParentIds(tempIds))) { resultList.addAll(descendants); tempIds.clear(); tempIds = descendants.stream().map(User::getId).collect(Collectors.toList()); } return resultList; } public List<User> getListByParentIds (List<Integer> tempIds) {}
Find self and descendant ids
private List<Integer> findSelfAndDescendantIds (Integer parentId) { List<Integer> resultIds = new ArrayList <>(); resultIds.add(id); List<Integer> tempIds = new ArrayList <>(); tempIds.add(parentId); List<Integer> childrenIds = null ; while (!CollectionUtils.isEmpty(childrenIds = getChildrenIdsByParentIds(tempIds))) { resultIds.addAll(childrenIds); tempIds.clear(); tempIds.addAll(childrenIds); } return resultIds; } public List<Integer> getChildrenIdsByParentIds (List<Integer> parentIds) {}
public Set<Integer> getDescendantIds (Integer deptId) { List<Object> descendantIds = new ArrayList <>(); List<Object> childIds = this .baseMapper.selectObjs(new LambdaQueryWrapper <SysDept>() .select(SysDept::getDeptId) .eq(SysDept::getParentId, deptId)); while (!CollectionUtils.isEmpty(childIds)) { descendantIds.add(childIds); childIds = this .baseMapper.selectObjs(new LambdaQueryWrapper <SysDept>() .select(SysDept::getDeptId) .in(SysDept::getParentId, childIds)); } return descendantIds.stream() .map(Objects::toString) .filter(Objects::nonNull) .map(Integer::valueOf) .collect(Collectors.toSet()); }
Operation Traversal Array Traversal
for (int i = 0; i < array.length; i++) {...}
Arrays.stream(array).xxx
List Traversal
for loop: for (int i = 0; i < list.size(); i++) {...}
enhanced for loop: for (Object o : list) {...}
iterator or listIterator
list.forEach(comsumer...)
list.stream().xxx
Handling List piece by piece public static void main (String[] args) { List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 ); int listSize = list.size(); int handlingSize = 3 ; int startIndex = 0 ; int endIndex = handlingSize; while (startIndex < listSize) { if (endIndex > listSize) { endIndex = listSize; } handleList(list, startIndex, endIndex); startIndex = endIndex; endIndex = startIndex + handlingSize; } } private static void handleList (List<Integer> list, int start, int end) { for (int i = start; i < end; i++) { System.out.println(list.get(i)); } }
Map Traversal
for (String key : map.keySet()) {...}
for (Map.entry entry : map.entrySet()) {...}
Iterator
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Integer> entry = iterator.next(); System.out.println(entry.getKey() + ":" + entry.getValue()); }
map.forEach(biComsumer...)
map.forEach((k, v) -> System.out.println((k + ":" + v)));
map.entrySet().stream()
forEach() vs stream()
If you just want to consume list, you best to choose forEach(), else stream().
Print collections Array
int a[] = new int []{1 , 2 , 3 };System.out.println(Arrays.toString(a));
List, Set
System.out.println(list); System.out.println(set);
Map
Map<String, Integer> map = new HashMap <>(); map.put("a" , 1 ); map.put("b" , 2 ); System.out.println(Arrays.toString(map.entrySet().toArray())); System.out.println(Arrays.asList(map.entrySet().toArray())); System.out.println(Arrays.asList(map)); System.out.println(map.entrySet().stream().map(entry -> entry.getKey() + ": " + entry.getValue()).collect(Collectors.joining(", " )));
HttpServletRequest’s ParameterMap
System.out.println(map.keySet().stream().map(key -> key + ": " + request.getParameter(key)).collect(Collectors.joining(", " )));
Join Use stream
List<String> names = Arrays.asList("Tom" , "Jack" , "Lucy" ); System.out.println(names.stream().map(Object::toString).collect(Collectors.joining("," ))); List<Integer> ids = Arrays.asList(1 , 2 , 3 ); System.out.println(ids.stream().map(Object::toString).collect(Collectors.joining("," )));
Use String.join()
List<String> names = Arrays.asList("Tom" , "Jack" , "Lucy" ); System.out.println(String.join("," , names));
Remove elements from collection List<Book> books = new ArrayList<Book>(); books.add(new Book(new ISBN("0-201-63361-2"))); books.add(new Book(new ISBN("0-201-63361-3"))); books.add(new Book(new ISBN("0-201-63361-4")));
Collect objects set and removeAll()
Swap position of elements and create new collection copy from updated old collection. Don’t reorganize the collection.
T(n) = O(n), S(n) = O(n)
ISBN isbn = new ISBN("0-201-63361-2"); List<Book> found = new ArrayList<>(); for(Book book : books){ if(book.getIsbn().equals(isbn)){ found.add(book); } } books.removeAll(found);
1.2 Collect indexes and remove one by one
T(n) = O(n), S(n) = O(m * n)
1.3 Collect objects set and remove one by one
T(n) = O(n), S(n) = O(m * n)
Using iterator to remove in loop
Iterator using the cursor variable to traverse collection and remove by index of collection. If you remove a element, the cursor will update correctly. Iterator like forEach, but it index is not from 0 to size-1 of collection. The every remove operations will creating a new collection that copy from updated old collection.
T(n) = O(n), S(n) = O(m * n)
ListIterator<Book> iter = books.listIterator(); while(iter.hasNext()){ if(iter.next().getIsbn().equals(isbn)){ iter.remove(); } }
removeIf() method (JDK 8)
Swap position of elements, set new size for collection, and set null for between new size to old size elements.
T(n) = O(n), S(n) = O(1)
ISBN other = new ISBN("0-201-63361-2"); books.removeIf(b -> b.getIsbn().equals(other));
Using filter of Stream API (JDK 8)
Creating new collection. Traversing has no order.
T(n) = O(n), S(n) = O(n) guess by “A stream does not store data and, in that sense, is not a data structure. It also never modifies the underlying data source.”
ISBN other = new ISBN("0-201-63361-2"); List<Book> filtered = books.stream() .filter(b -> b.getIsbn().equals(other)) .collect(Collectors.toList());
Recommend: removeIf() > stream().filter() or parallelStream()> Collect objects set and removeAll() > Using iterator, or Collect indexes and remove one by one, or Collect objects set and remove one by one.
Deduplication Deduplicate values
Deduplicate values by stream distinct()
List<Integer> list = Arrays.asList(1 , 2 , 3 , 2 , 3 , 4 ); list = list.stream().distinct().collect(Collectors.toList()); System.out.println(list);
Deduplicate values by creating a set
List<Integer> list = new ArrayList <>(Arrays.asList(1 , 2 , 3 , 2 , 3 , 4 )); Set<Integer> set = new LinkedHashSet <>(list); list.clear(); list.addAll(set); System.out.println(list);
List<Integer> list = Arrays.asList(1 , 2 , 3 , 2 , 3 , 4 ); list = new ArrayList <>(new LinkedHashSet <>(list)); System.out.println(list);
Deduplicate objects by property
Deduplicate by streamList<User> list = list.stream().collect(Collectors.toMap(User::getName, Function.identity(), (p, q) -> p, LinkedHashMap::new )).values();
Deduplicate objects by removing in for loopList<User> userList = buildUserList(); System.out.println("Before: " + userList); Iterator<User> i = userList.iterator(); while (i.hasNext()) { User user = i.next(); if (user.getUserName().contains("test" )) { i.remove(); } } System.out.println("After: " + userList);
Deduplicate objects by finding duplicate objects and then removing all of it
List<User> userList = buildUserList(); System.out.println("Before: " + userList); List<User> toRemoveList = new ArrayList <>(); for (User user : userList) { if (user.getUserName().contains("test" )) { toRemoveList.add(user); } } userList.removeAll(toRemoveList); System.out.println("After: " + userList);
Only one consecutive repeated element is retained List<IdName> list = new ArrayList <>(); list.add(new IdName (1 , "a" )); list.add(new IdName (2 , "a" )); list.add(new IdName (3 , "a" )); list.add(new IdName (4 , "b" )); list.add(new IdName (5 , "b" )); list.add(new IdName (6 , "c" )); List<Integer> indexToRemove = new ArrayList <>(); for (int i = 0 ; i < list.size(); i++) { if (i < list.size() - 1 && list.get(i).getName().equals(list.get(i + 1 ).getName())) { indexToRemove.add(i); } } for (int i = indexToRemove.size() - 1 ; i >= 0 ; i--) { list.remove(indexToRemove.get(i).intValue()); } System.out.println(list);
Output
[IdName(id=3, name=a), IdName(id=5, name=b), IdName(id=6, name=c)]
Ordered Collections
Sorted Collection Classes
Inserted order Collection Classes
LinkedList
LinkedHashSet
LinkedHashMap
Sorting
Using Collections.sort(list) to sort Comparable elements
It uses merge sort. T(n) = O(log n)
sort(List<T> list)
sort(List<T> list, Comparator c)
Comparators
Comparator.naturalOrder()
Comparator.comparing(Function f)
Comparator.comparingInt(Function f)
Collections.reverseOrder()
Collections.reverseOrder(Comparator c)
(o1, o2) -> o1.getType().compareTo(o2.getType()) equals Comparator.comparing(User::getType)
Multiple fields with comparator
Comparator<Employee> compareByFirstName = Comparator.comparing(Employee::getFirstName); Comparator<Employee> compareByLastName = Comparator.comparing(Employee::getLastName); Comparator<Employee> compareByFullName = compareByFirstName.thenComparing(compareByLastName);
Comparator<Employee> compareByName = Comparator .comparing(Employee::getFirstName) .thenComparing(Employee::getLastName);
Comparator<IdName> c = (o1, o2) -> { int i = o1.getFirstName().compareTo(o2.getFirstName()); if (i != 0 ) { return i; } return o1.getLastName().compareTo(o2.getLastName()); };
Comparators avoid NullPointerException
Comparator<Employee> compareByName = Comparator .comparing(Employee::getFirstName, Comparator.nullsLast(Comparator.naturalOrder())) .thenComparing(Employee::getLastName, Comparator.nullsLast(Comparator.naturalOrder()));
Comparator<IdName> c = (o1, o2) -> { if (o1.getId() == null ) { return 1 ; } else if (o2.getId() == null ) { return -1 ; } int i = o1.getId().compareTo(o2.getId()); if (i != 0 ) { return i; } if (o1.getName() == null ) { return 1 ; } else if (o2.getName() == null ) { return -1 ; } return o1.getName().compareTo(o2.getName()); };
Stream.sorted()
List<Integer> list = new ArrayList <>(Arrays.asList(1 , 3 , 2 , 6 , 5 , 4 , 9 , 7 )); list.stream().sorted().forEachOrdered(System.out::print); list.stream().sorted((o1, o2) -> o1 - o2).forEachOrdered(System.out::print); list.stream().sorted(Comparator.comparingInt(o -> o)).forEachOrdered(System.out::print);
Summary: if you don’t need to keep collections always be ordered, you just use Collections sort() to get sorted collections.
Compare object list using Collections.sort(objectList)
public class Animal implements Comparable<Animal> { private String name; @Override public int compareTo(Animal o) { return this.name.compareTo(o.name); } }
List<Animal> list = new ArrayList <>(); Collections.sort(list); Collections.sort(list, Collections.reverseOrder());
Reversion
Using void Collections.reverse(list)
List list = Arrays.asList("a" , "b" , "c" );Collections.reverse(list); System.out.println(list);
Using for loop
List<String> list = Arrays.asList("a" , "b" , "c" ); for (int i = 0 ; i < list.size() / 2 ; i++) { String temp = list.get(i); list.set(i, list.get(list.size() - i - 1 )); list.set(list.size() - i - 1 , temp); } System.out.println(list);
Using recursion
private static void reverse (List<String> list) { if (list == null || list.size() <= 1 ) { return ; } String value = list.remove(0 ); reverse(list); list.add(value); } public static void main (String[] args) { List<String> list = new ArrayList <>(Arrays.asList("a" , "b" , "c" , "d" )); reverse(list); System.out.println(list); }
Items in a stream map to lists and collect all lists to one list Using Stream.flatMap()
List<Integer> list = Arrays.asList(1 , 2 , 3 ); Map<Integer, List<String>> map = new HashMap <>(); map.put(1 , Arrays.asList("a" , "b" )); map.put(2 , Arrays.asList("c" , "d" )); List<String> resultList = list.stream().flatMap(item -> Optional.ofNullable(map.get(item)) .map(List::stream) .orElse(Stream.empty())) .collect(Collectors.toList()); System.out.println(resultList);
Computation Reduction for loop
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 ); int sum = 0 ;for (int x : numbers) { sum += x; }
stream
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 ); int sum = numbers.stream().reduce(0 , (x, y) -> x + y);
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 ); int sum = numbers.stream().reduce(0 , Integer::sum);
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 ); Integer sum = numbers.stream().collect(Collectors.summingInt(Integer::intValue));
parallel stream (operations can run safely in parallel with almost no modification)
int sum = numbers.parallelStream().reduce(0 , Integer::sum);
Group and aggregation Group
groupingBy()
partitioningBy()
Map<Department, List<Employee>> byDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment)); Map<Integer, Set<Integer>> userToRoleIds = userRoles.stream().collect(Collectors.groupingBy(UserRole::getUserId, Collectors.mapping(AssignmentDept::getRoleId, Collectors.toSet()))); Map<Boolean, List<Student>> passingFailing = students.stream() .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
Aggregation
max(), maxBy()
min(), minBy()
average(), averagingInt()
sum(), summingInt()
counting()
Max
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 );
max()
int max = numbers .stream() .mapToInt(Integer::intValue) .max() .orElse(0 );
maxBy()
int max = numbers.stream(). collect(Collectors.maxBy(Comparator.naturalOrder())) .orElse(0 ); System.out.println(max);
Average
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 );
average()
double average = numbers .stream() .mapToInt(Integer::intValue) .average() .orElse(0.0 ); System.out.println(average);
averagingInt()
double average = numbers.stream().collect(Collectors.averagingInt(a -> a));System.out.println(average);
Sum
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 );
sum()
int sum = numbers .stream() .mapToInt(a -> a) .sum(); System.out.println(sum);
summingInt()
int sum = numbers.stream().collect(Collectors.summingInt(Integer::intValue));
summarizingInt()
long sum = Stream.of(1 , 2 , 3 ) .collect(Collectors.summarizingInt(Integer::intValue)) .getSum();
Sum of each group
Map<Department, Integer> totalByDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));
Sort by grouped fields
Map<String, Double> averageAgeByType = userList .stream() .collect(Collectors.groupingBy(User::getType, TreeMap::new , Collectors.averagingInt(User::getAge)));
Map<String, Double> userAverageAgeMap2 = userList .stream() .sorted(Comparator.comparing(User::getType)) .collect(Collectors.groupingBy(User::getType, LinkedHashMap::new , Collectors.averagingInt(User::getAge)));
Java Code Example articles
References