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); 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 );
Collections Construction Collection Element Type Conversion String to Object
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 to String
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, Map
System.out.println(list); System.out.println(set); System.out.println(map);
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 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
maxBy()
minBy()
averagingInt()
summingInt()
counting()
Map<Department, Integer> totalByDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));
List<Integer> numbers = Arrays.asList(1 , 2 , 3 , 4 , 5 ); Integer sum = numbers.stream().collect(Collectors.summingInt(Integer::intValue));
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)));
References