<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
對於陣列遍歷,基本上每個開發者都寫過,遍歷本身沒什麼好說的,但是當我們在遍歷的過程中,有一些複雜的業務邏輯時,將會發現程式碼的層級會逐漸加深
如一個簡單的case,將一個二維陣列中的偶數找出來,儲存到一個列表中
二維陣列遍歷,每個元素判斷下是否為偶數,很容易就可以寫出來,如:
public void getEven() { int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}}; List<Integer> ans = new ArrayList<>(); for (int i = 0; i < cells.length; i ++) { for (int j = 0; j < cells[0].length; j++) { if ((cells[i][j] & 1) == 0) { ans.add(cells[i][j]); } } } System.out.println(ans); }
上面這個實現沒啥問題,但是這個程式碼的深度很容易就有三層了;當上面這個if中如果再有其他的判定條件,那麼這個程式碼層級很容易增加了;二維陣列還好,如果是三維陣列,一個遍歷就是三層;再加點邏輯,四層、五層不也是分分鐘的事情麼
那麼問題來了,程式碼層級變多之後會有什麼問題呢?
只要程式碼能跑,又能有什麼問題呢?!
由於多維陣列的遍歷層級天然就很深,那麼有辦法進行消減麼?
要解決這個問題,關鍵是要抓住重點,遍歷的重點是什麼?獲取每個元素的座標!那麼我們可以怎麼辦?
定義一個函數方法,輸入的就是函數座標,在這個函數體中執行我們的遍歷邏輯即可
基於上面這個思路,相信我們可以很容易寫一個二維的陣列遍歷通用方法
public static void scan(int maxX, int maxY, BiConsumer<Integer, Integer> consumer) { for (int i = 0; i < maxX; i++) { for (int j = 0; j < maxY; j++) { consumer.accept(i, j); } } }
主要上面的實現,函數方法直接使用了JDK預設提供的BiConsumer,兩個傳參,都是int 陣列下表;無返回值
那麼上面這個怎麼用呢?
同樣是上面的例子,改一下之後,如:
public void getEven() { int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}}; List<Integer> ans = new ArrayList<>(); scan(cells.length, cells[0].length, (i, j) -> { if ((cells[i][j] & 1) == 0) { ans.add(cells[i][j]); } }); System.out.println(ans); }
相比於前面的,貌似也就少了一層而已,好像也沒什麼了不起的
但是,當陣列變為三維、四維、無維時,這個改動的寫法層級都不會變哦
前面的實現對於正常的遍歷沒啥問題;但是當我們在遍歷過程中,遇到某個條件直接返回,能支援麼?
如一個遍歷二維陣列,我們希望判斷其中是否有偶數,那麼可以怎麼整?
仔細琢磨一下我們的scan方法,希望可以支援return,主要的問題點就是這個函數方法執行之後,我該怎麼知道是繼續迴圈還是直接return呢?
很容易想到的就是執行邏輯中,新增一個額外的返回值,用於標記是否中斷迴圈直接返回
基於此思路,我們可以實現一個簡單的demo版本
定義一個函數方法,接受迴圈的下標 + 返回值
@FunctionalInterface public interface ScanProcess<T> { ImmutablePair<Boolean, T> accept(int i, int j); }
迴圈通用方法就可以相應的改成:
public static <T> T scanReturn(int x, int y, ScanProcess<T> func) { for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { ImmutablePair<Boolean, T> ans = func.accept(i, j); if (ans != null && ans.left) { return ans.right; } } } return null; }
基於上面這種思路,我們的實際使用姿勢如下:
@Test public void getEven() { int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}}; List<Integer> ans = new ArrayList<>(); scanReturn(cells.length, cells[0].length, (i, j) -> { if ((cells[i][j] & 1) == 0) { return ImmutablePair.of(true, i + "_" + j); } return ImmutablePair.of(false, null); }); System.out.println(ans); }
上面這個實現可滿足我們的需求,唯一有個彆扭的地方就是返回,總有點不太優雅;那麼除了這種方式之外,還有其他的方式麼?
既然考慮了返回值,那麼再考慮一下傳參呢?通過一個定義的引數來裝在是否中斷以及返回結果,是否可行呢?
基於這個思路,我們可以先定義一個引數包裝類:
public static class Ans<T> { private T ans; private boolean tag = false; public Ans<T> setAns(T ans) { tag = true; this.ans = ans; return this; } public T getAns() { return ans; } } public interface ScanFunc<T> { void accept(int i, int j, Ans<T> ans) }
我們希望通過Ans這個類來記錄迴圈結果,其中tag=true,則表示不用繼續迴圈了,直接返回ans結果吧
與之對應的方法改造及範例如下:
public static <T> T scanReturn(int x, int y, ScanFunc<T> func) { Ans<T> ans = new Ans<>(); for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { func.accept(i, j, ans); if (ans.tag) { return ans.ans; } } } return null; } public void getEven() { int[][] cells = new int[][]{{1, 2, 3, 4}, {11, 12, 13, 14}, {21, 22, 23, 24}}; String ans = scanReturn(cells.length, cells[0].length, (i, j, a) -> { if ((cells[i][j] & 1) == 0) { a.setAns(i + "_" + j); } }); System.out.println(ans); }
這樣看起來就比前面的要好一點了
實際跑一下,看下輸出是否和我們預期的一致;
到此這篇關於Java技巧函數方法實現二維陣列遍歷的文章就介紹到這了,更多相關Java陣列遍歷內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45