不要再寫這樣的神級代碼了!


關注公眾號(CoderBuff)回復“stream”獲取《Java8 Stream編碼實戰》PDF完整版。

JDK8提供的Stream雖然好用,Lambda雖然簡潔,但一定不能濫用,我舉一個實際遇到的例子(已做脫敏處理):

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表達式實在沒辦法讀下去了,根本不知道他想表達什么意思。

但是,如果我們真正遇到這樣的“大神級”代碼怎么辦?還好有IDEA這樣的神奇幫助我們,鼠標移動到代碼處,點擊右鍵出現以下菜單:

點擊“Show Context Actions”,出現以下內容:

選擇“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表達式,別說優化,連看懂都是問題。當我們把代碼改為“傳統”代碼后,邏輯一下就清晰了。

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這樣是不是更好呢?

關注公眾號(CoderBuff)回復“stream”獲取《Java8 Stream編碼實戰》PDF完整版。

這是一個能給程序員加buff的公眾號 (CoderBuff)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM