文章插圖

文章插圖
唐宋八大家之一歐陽修在《賣油翁》中寫道:
翁取一葫蘆置于地,以錢覆其口,徐以杓酌油瀝之,自錢孔入,而錢不濕 。因曰:“我亦無他,唯手熟爾 ?!?br /> 【判斷數組是不是空 js如何判斷數組是否為空】編寫代碼的”老司機”也是如此,”老司機”之所以被稱為”老司機”,原因也是”無他,唯手熟爾” 。編碼過程中踩過的坑多了,獲得的編碼經驗也就多了,總結的編碼技巧也就更多了 。總結的編碼技巧多了,凡事又能夠舉一反三,編碼的速度自然就上來了 。筆者從數據結構的角度,整理了一些 Java 編程技巧,以供大家學習參考 。
HashSet 實現 Set 接口,由哈希表(實際上是 HashMap )實現,但不保證 set 的迭代順序,并允許使用 元素 。HashSet 的時間復雜度跟 HashMap 一致,如果沒有哈希沖突則時間復雜度為 O(1) ,如果存在哈希沖突則時間復雜度不超過 O(n)。所以,在日常編碼中,可以使用 HashSet 判斷主鍵是否存在 。
案例:給定一個字符串(不一定全為字母),請返回第一個重復出現的字符 。
/** 查找第一個重復字符 */public static char findFirstRepeatedChar(String string) {// 檢查空字符串if (Objects.is(string) || string.isEmpty) {return ;}// 查找重復字符char charArray = string.toCharArray;Set charSet = new HashSet<>(charArray.length);for (char ch : charArray) {if (charSet.contains(ch)) {return ch;}charSet.add(ch);}// 默認返回為空return ;}其中,由于 Set 的 add 函數有個特性——如果添加的元素已經再集合中存在,則返回 false??梢院喕a為:if (!charSet.add(ch)) {return ch;}簡單來說,HashMap 由數組和鏈表組成的,數組是 HashMap 的主體,鏈表則是主要為了解決哈希沖突而存在的 。如果定位到的數組位置不含鏈表,那么查找、添加等操作很快,僅需一次尋址即可,其時間復雜度為 O(1) ;如果定位到的數組包含鏈表,對于添加操作,其時間復雜度為 O(n) ——首先遍歷鏈表,存在即覆蓋,不存在則新增;對于查找操作來講,仍需要遍歷鏈表,然后通過key對象的 equals 方法逐一對比查找 。從性能上考慮, HashMap 中的鏈表出現越少,即哈希沖突越少,性能也就越好 。所以,在日常編碼中,可以使用 HashMap 存取鍵值映射關系 。
案例:給定菜單記錄列表,每條菜單記錄中包含父菜單標識(根菜單的父菜單標識為 ),構建出整個菜單樹 。
/** 菜單DO類 [email protected]@[email protected] static class MenuDO {/** 菜單標識 */private Long id;/** 菜單父標識 */private Long parentId;/** 菜單名稱 */private String name;/** 菜單鏈接 */private String url;}/** 菜單VO類 [email protected]@[email protected] static class MenuVO {/** 菜單標識 */private Long id;/** 菜單名稱 */private String name;/** 菜單鏈接 */private String url;/** 子菜單列表 */private List<MenuVO> childList;}/** 構建菜單樹函數 */public static List<MenuVO> buildMenuTree(List<MenuDO> menuList) {// 檢查列表為空if (CollectionUtils.isEmpty(menuList)) {return Collections.emptyList;}// 依次處理菜單int menuSize = menuList.size;List<MenuVO> rootList = new ArrayList<>(menuSize);Map<Long, MenuVO> menuMap = new HashMap<>(menuSize);for (MenuDO menuDO : menuList) {// 賦值菜單對象Long menuId = menuDO.getId;MenuVO menu = menuMap.get(menuId);if (Objects.is(menu)) {menu = new MenuVO;menu.setChildList(new ArrayList<>);menuMap.put(menuId, menu);}menu.setId(menuDO.getId);menu.setName(menuDO.getName);menu.setUrl(menuDO.getUrl);// 根據父標識處理Long parentId = menuDO.getParentId;if (Objects.non(parentId)) {// 構建父菜單對象MenuVO parentMenu = menuMap.get(parentId);if (Objects.is(parentMenu)) {parentMenu = new MenuVO;parentMenu.setId(parentId);parentMenu.setChildList(new ArrayList<>);menuMap.put(parentId, parentMenu);}// 添加子菜單對象parentMenu.getChildList.add(menu);} else {// 添加根菜單對象rootList.add(menu);}}// 返回根菜單列表return rootList;}使用 ThreadLocal 存儲線程專有對象ThreadLocal 提供了線程專有對象,可以在整個線程生命周期中隨時取用,極大地方便了一些邏輯的實現 。
常見的 ThreadLocal 用法主要有兩種:
1、保存線程上下文對象,避免多層級參數傳遞;
2、保存非線程安全對象,避免多線程并發調用 。
保存線程上下文對象,避免多層級參數傳遞
這里,以 PageHelper 插件的源代碼中的分頁參數設置與使用為例說明 。
設置分頁參數代碼:
/** 分頁方法類 */public abstract class PageMethod {/** 本地分頁 */protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>;/** 設置分頁參數 */protected static void setLocalPage(Page page) {LOCAL_PAGE.set(page);}/** 獲取分頁參數 */public static <T> Page<T> getLocalPage {return LOCAL_PAGE.get;}/** 開始分頁 */public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {Page<E> page = new Page<E>(pageNum, pageSize, count);page.setReasonable(reasonable);page.setPageSizeZero(pageSizeZero);Page<E> oldPage = getLocalPage;if (oldPage != && oldPage.isOrderByOnly) {page.setOrderBy(oldPage.getOrderBy);}setLocalPage(page);return page;}}使用分頁參數代碼:/** 虛輔助方言類 */public abstract class AbstractHelperDialect extends AbstractDialect implements Constant {/** 獲取本地分頁 */public <T> Page<T> getLocalPage {return PageHelper.getLocalPage;}/** 獲取分頁SQL [email protected] String getPageSql(M
- 米糕用的米是什么米是不是糯米嗎,米糕用什么米做最好吃
- 發芽的大蒜是不是有毒,蒜發苦了還能吃嗎
- 怎樣判斷女人出軌了,怎么判斷女生和其他男生有沒有關系?
- 夏天高層樓頂是不是特殊熱
- 番石榴怎么判斷熟了
- 怎么看出女生睡過多少人 判斷女朋友和多少人睡過
- 怎樣判斷女人出軌了:如何判斷妻子是否有外遇?
- 淘寶流量推廣軟件是真的嗎 淘寶推廣是不是真的
- 看看你的孩子是不是這樣 看看你的他是不是這樣
- matlab一維數組索引 matlab二維矩陣索引
