首页 文章 精选 留言 我的

精选列表

搜索[Java],共10000篇文章
优秀的个人博客,低调大师

SAP BSP, Java Web Project,Android和微信小程序的初始页面设置

CRM Webclient UI Component controller的context DO_INIT_CONTEXT: 然后是Window controller的DO_INIT_CONTEXT: 最后才是view controller的DO_INIT_CONTEXT: Android 微信小程序 (1) onLoad 生命周期函数--监听页面加载(2) onReady 生命周期函数--监听页面初次渲染完成(3) onShow 生命周期函数--监听页面显示(4) onHide 生命周期函数--监听页面隐藏(5) onUnload 生命周期函数--监听页面卸载 打开小程序后会依次执行onLoad,onReady和onShow方法. 前后台切换会分别执行onHide和onShow方法 本文来自云栖社区合作伙伴“汪子熙”,了解相关信息可以关注微信公众号"汪子熙"。

优秀的个人博客,低调大师

为什么说LinkedHashMap是Java中最大的数据结构? 了解一下?

云栖号:https://yqh.aliyun.com第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策! Map 家族数量众多,其中 HashMap 和 ConcurrentHashMap 用的最多,而 LinkedHashMap 似乎则是不怎么用的,但是他却有着顺序。两种,一种是添加顺序,一种是访问顺序。 LinkedHashMap 继承了 HashMap。那么如果是你,你怎么实现这两个顺序呢? 如果实现添加顺序的话,我们可以在该类中,增加一个链表,每个节点对应 hash 表中的桶。这样,循环遍历的时候,就可以按照链表遍历了。只是会增大内存消耗。 如果实现访问顺序的话,同样也可以使用链表,但每次读取数据时,都需要更新一下链表,将最近一次读取的放到链尾。这样也就能够实现。此时也可以跟进这个特性实现 LRU(Least Recently Used) 缓存。 如何使用? 下面是个小 demo LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>(16, 0.75f, true); for (int i = 0; i < 10; i++) { map.put(i, i); } for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue()); } map.get(3); System.out.println(); for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue()); } 打印结果: 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 8:8 9:9 0:0 1:1 2:2 4:4 5:5 6:6 7:7 8:8 9:9 3:3 首先构造方法是有意思的,比 HashMap 多了一个 accessOrder boolean 参数。表示,按照访问顺序来排序。最新访问的放在链表尾部。 如果是默认的,则是按照添加顺序,即 accessOrder 默认是 false。 源码实现 如果看 LinkedHashMap 内部源码,会发现,内部确实维护了一个链表: /** * 双向链表的头,最久访问的 */ transient LinkedHashMap.Entry<K,V> head; /** * 双向链表的尾,最新访问的 */ transient LinkedHashMap.Entry<K,V> tail; 而这个 LinkedHashMap.Entry 内部也维护了双向链表必须的元素,before,after: /** * HashMap.Node subclass for normal LinkedHashMap entries. */ static class Entry<K,V> extends HashMap.Node<K,V> { Entry<K,V> before, after; Entry(int hash, K key, V value, Node<K,V> next) { super(hash, key, value, next); } } 在添加元素的时候,会追加到尾部。 Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) { LinkedHashMap.Entry<K,V> p = new LinkedHashMap.Entry<K,V>(hash, key, value, e); linkNodeLast(p); return p; } // link at the end of list private void linkNodeLast(LinkedHashMap.Entry<K,V> p) { LinkedHashMap.Entry<K,V> last = tail; tail = p; if (last == null) head = p; else { p.before = last; last.after = p; } } 在 get 的时候,会根据 accessOrder 属性,修改链表顺序: public V get(Object key) { Node<K,V> e; if ((e = getNode(hash(key), key)) == null) return null; if (accessOrder) afterNodeAccess(e); return e.value; } void afterNodeAccess(Node<K,V> e) { // move node to last LinkedHashMap.Entry<K,V> last; if (accessOrder && (last = tail) != e) { LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; p.after = null; if (b == null) head = a; else b.after = a; if (a != null) a.before = b; else last = b; if (last == null) head = p; else { p.before = last; last.after = p; } tail = p; ++modCount; } } 同时注意:这里修改了 modCount,即使是读操作,并发也是不安全的。 如何实现 LRU 缓存? LRU 缓存:LRU(Least Recently Used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。LinkedHashMap 并没有帮我我们实现具体,需要我们自己实现 。具体实现方法是 removeEldestEntry 方法。一起来看看原理。 首先,HashMap 在 putVal 方法最后,会调用 afterNodeInsertion 方法,其实就是留给 LinkedHashMap 的。而 LinkedHashMap 的具体实现则是根据一些条件,判断是否需要删除 head 节点。 源码如下: void afterNodeInsertion(boolean evict) { // possibly remove eldest LinkedHashMap.Entry<K,V> first; if (evict && (first = head) != null && removeEldestEntry(first)) { K key = first.key; removeNode(hash(key), key, null, false, true); } } evict 参数表示是否需要删除某个元素,而这个 if 判断需要满足的条件如上:head 不能是 null,调用 removeEldestEntry 方法,返回 true 的话,就删除这个 head。而这个方法默认是返回 false 的,等待着你来重写。 所以,removeEldestEntry 方法的实现通常是这样: public boolean removeEldestEntry(Map.Entry<K, V> eldest){ return size() > capacity; } 如果长度大于容量了,那么就需要清除不经常访问的缓存了。afterNodeInsertion 会调用 removeNode 方法,删除掉 head 节点 —— 如果 accessOrder 是 true 的话,这个节点就是最不经常访问的节点。 拾遗 LinkedHashMap 重写了一些 HashMap 的方法,例如 containsValue 方法,这个方法大家猜一猜,怎么重写比较合理?HashMap 使用了双重循环,先循环外层的 hash 表,再循环内层的 entry 链表。性能可想而知。 但 LinkedHashMap 内部有个元素链表,直接遍历链表就行。相对而言而高很多。 public boolean containsValue(Object value) { for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) { V v = e.value; if (v == value || (value != null && value.equals(v))) return true; } return false; } 这也算一种空间换时间的策略吧。 get 方法当然也是要重写的。因为需要根据 accessOrder 更新链表。 总结 雪薇的总结的一下: LinkedHashMap 内部包含一个双向链表维护顺序,支持两种顺序——添加顺序,访问顺序。 默认就是按照添加顺序来的,如果要改成访问顺序的话,构造方法中的 accessOrder 需要设置成 true。这样,每次调用 get 方法,就会将刚刚访问的元素更新到链表尾部。 关于 LRU,在accessOrder 为 true 的模式下,你可以重写 removeEldestEntry 方法,返回 size() > capacity,这样,就可以删除最不常访问的元素。 原文发布时间:2020-01-09本文作者:莫那一鲁道本文来自阿里云云栖号合作伙伴“互联网架构师”,了解相关信息可以关注“互联网架构师” 云栖号:https://yqh.aliyun.com第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策!

优秀的个人博客,低调大师

JAVA描述算法和数据结构(01):稀疏数组和二维数组转换

本文源码:GitHub·点这里 || GitEE·点这里 一、基本简介 1、基础概念 在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。 2、处理方式 1)、记录数组一共有几行几列,有多少个不同的值 2)、把具有不同值的元素的行列及值记录在稀疏数组中,可以缩小程序代码的复杂度。 3、图解描述 稀疏数组表示 [0] 3 4 4 二维数组,3行,4列,4个非0的值; [1] 1 2 2 一行,2列的值是2; [2] 1 3 3 一行,3列的值是3; …以此类推 4、五子棋场景 使用稀疏数组描述 行 列 值 [0] 11 11 2 [1] 1 2 1 [2] 2 3 2 二、代码实现 1、转换流程 二维数组转稀疏数组 1)、遍历二维数组,得到非零元素的个数 2)、创建稀疏数组 3)、二维数组的非零元素写入稀疏数组 稀疏数组转二维数组 1)、读取稀疏数组的首行,创建二维数组 2)、根据稀疏数组描述的有效元素,给二维数组赋值 2、代码实现 1)、核心流程 1、棋盘:基于二维数组 2、二维数组转稀疏数组 3、稀疏数组转二维数组 2)、方法一:生成二维数组 public static int[][] printChess (){ // 二维数组表示 11 * 11 的棋盘,0表示没有棋,1表示 黑, 2 表示蓝 int chessArray[][] = new int[11][11]; chessArray[1][2] = 1; chessArray[2][3] = 2; for (int[] row : chessArray) { for (int data : row) { System.out.printf("%d\t", data); } System.out.println(); } return chessArray ; } 3)、方法二:转为稀疏数组 public static int[][] convertTwoArray (int chessArray[][]){ // 有效元素:先遍历二维数组 得到非0数据的个数 int unZeroSum = 0; for (int i = 0; i < 11; i++) { for (int j = 0; j < 11; j++) { if (chessArray[i][j] != 0) { unZeroSum++; } } } // 行:有效元素+1,列:3列 int sparseArray[][] = new int[unZeroSum+1][3] ; sparseArray[0][0] = 11 ;// 0行0列值:11 sparseArray[0][1] = 11 ;// 0行1列值:11 sparseArray[0][2] = unZeroSum ;// 0行2列值:unZeroSum // 遍历二维数组,将非0的值存放到稀疏数组中 // unZeroCount 用于记录是第几个非0数据,也就是稀疏数组的行 int unZeroCount = 0; // for (int i = 0; i < 11; i++) { for (int j = 0; j < 11; j++) { if (chessArray[i][j] != 0) { unZeroCount++; sparseArray[unZeroCount][0] = i; sparseArray[unZeroCount][1] = j; sparseArray[unZeroCount][2] = chessArray[i][j]; } } } // 输出稀疏数组的形式 for (int i = 0; i < sparseArray.length; i++) { System.out.printf("%d\t%d\t%d\t\n", sparseArray[i][0], sparseArray[i][1], sparseArray[i][2]); } return sparseArray ; } 4)、方法三:转为二维数组 public static void convertSparseArray (int sparseArray[][]){ // 读取稀疏数组首行创建二维数组==>> int chessArray[][] = new int[11][11]; int chessArray[][] = new int[sparseArray[0][0]][sparseArray[0][1]] ; // 非零元素赋值给二维数组 for(int i = 1; i < sparseArray.length; i++) { // 几行、几列、是什么值 chessArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2]; } // 打印二维数组 for (int[] row : chessArray) { for (int data : row) { System.out.printf("%d\t", data); } System.out.println(); } } 5)、主程序调用 public static void main(String[] args) { // 棋盘:基于二维数组 int chessArray[][] = printChess () ; System.out.println("=========================="); // 二维数组转稀疏数组 int sparseArray[][] = convertTwoArray(chessArray) ; System.out.println("=========================="); // 稀疏数组转二维数组 convertSparseArray(sparseArray); } 三、源代码地址 GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册