JDK8提供的Stream雖然好用,Lambda雖然簡潔,但必定不能濫用,我舉一個實際遇到的例子(已作脫敏處理):java
Map<Long, List<Student>> studentMap = students.stream().collect(Collectors.groupingBy(Student::getStudentNumber)).entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
試問誰能看得懂?難道是沒有換行格式化?程序員
Map<Long, List<Student>> studentMap = students.stream().collect(Collectors.groupingBy(Student::getStudentNumber)) //這裏是要把students按studentNumber分組 .entrySet().stream().sorted(Map.Entry.comparingByKey()) //分組後再把把key值拿來排序組成新的Stream流 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, //而後再組成Map?很差意思實在是讀不下去了 (oldValue, newValue) -> oldValue, LinkedHashMap::new));
換行格式化後,前面的流操做還能勉強讀懂,遇到最後的lambda表達式實在沒辦法讀下去了,根本不知道他想表達什麼意思。app
可是,若是咱們真正遇到這樣的「大神級」代碼怎麼辦?還好有IDEA這樣的神奇幫助咱們,鼠標移動到代碼處,點擊右鍵出現如下菜單:ide
點擊「Show Context Actions」,出現如下內容:oop
選擇「Replace Stream API chain with loop(利用循環代替Stream流操做)」。優化
當我把全部的Stream流操做以及簡寫的lambda表達式用「傳統」代碼取代後,代碼邏輯以下:編碼
Map<Long, List<Student>> map = new HashMap<>(); //按step進行分組 for (Student student : students) { //computeIfAbsent方法等同下列代碼 /*List<Student> list = map.get(student.getStudentNumber()); if (list == null) { list = new ArrayList<>(); map.put(list); } list.add(student)*/ map.computeIfAbsent(student.getStudentNumber(), new Function<Long, List<Student>>() { @Override public List<Student> apply(Long k) { return new ArrayList<>(); } }).add(student); } //把Map的Entry元素放入List中,並排序 List<Map.Entry<Long, List<Student>>> toSort = new ArrayList<>(); for (Map.Entry<Long, List<Student>> integerListEntry : map .entrySet()) { toSort.add(integerListEntry); } toSort.sort(Map.Entry.comparingByKey()); //再使用LinkedHashMap按插入順序排列 Map<Long, List<Student>> studentkMap = new LinkedHashMap<>(); for (Map.Entry<Long, List<Student>> integerListEntry : toSort) { studentkMap.putIfAbsent(integerListEntry.getKey(), integerListEntry.getValue()); }
這樣看代碼邏輯清晰了,實際上不就是把List按元素中的step分組,並按字典序排列麼?若是按照開始的Stream+Lambda表達式,別說優化,連看懂都是問題。當咱們把代碼改成「傳統」代碼後,邏輯一下就清晰了。3d
Map<Long, List<Student>>> studentMap = new TreeMap<>(); for (Student student : students) { List<Student> list = map.get(student.getStudentNumber()); if (list == null) { list = new ArrayList<>(); map.put(list); } list.add(student) }
適當是使用Stream和Lambda這樣是否是更好呢?code
關注公衆號(CoderBuff)回覆「stream」獲取《Java8 Stream編碼實戰》PDF完整版。blog