问什么一直看我这个图片
欢迎加入 xiaozhi 大家族
首页
推荐
百度一下
腾讯视频
Search
1
小米手机安装CA证书 MIUI13 Android 12可用
540 阅读
2
欢迎家人
226 阅读
3
2020.09.01 HTML 笔记
214 阅读
4
微信公众号推送早安问候以及天气预报 尾部附源码下载链接
200 阅读
5
MP代码生成器
176 阅读
默认分类
HTML初学日记
Java 笔记
小智的生活日记
Java 实用技巧
java面试经典问题
登录
Search
标签搜索
java基础
HTML初学记录
java分享
java抛错
小智
累计撰写
76
篇文章
累计收到
2
条评论
今日撰写
0
篇文章
首页
栏目
默认分类
HTML初学日记
Java 笔记
小智的生活日记
Java 实用技巧
java面试经典问题
页面
推荐
百度一下
腾讯视频
用户登录
登录
搜索到
76
篇与
的结果
2020-11-02
HashMap
static class Node<K,V> implements Map.Entry<K,V>{//定义必要的属性 final int hash; final K key; V value; Node<K,V> next; //初始化 Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } //getKey public final K getKey() {return key;} public final V getValue() {return value;} public final String toString() {return key + "=" + value;} //重点,面试常备问道,求hashCode的值是key和value的异或 public final int hashCode(){return Objects.hashCode(key)^Objects.hashCode(value);} //需要暂存原始值,最后再返回 public final V setValue(V newValue){ V oldValue = value; value = newValue; return oldValue; } //需要重写equals,当key,value同时相等时,才相等 public final boolean equals(Object o){ if(o == this) return true; if(o instanceof Map.Entry){ Map.Entry<?,?> e = (Map.Entry<?,?>) o; if(Objects.equals(key,e.getKey()) && Objects.equals(value,e.getValue())) return true; } return false; } //hash是key值的hashcode高低16位异或,从这里可以知道jdk1.8hashmap的key是可以为null //若为null,取0,hashtable中的key是不能为null的 static final int hash(Object key){ int h; return (key == null)?0:(h = key.hashCode()^(h>>>16)); } //给出一个初始容量,会根据给定的初始容量,给出最近的2的多少平方 static final int tableSizeFor(int cap){ int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMU_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; } //同上,另一种实现方法,得到最近的2的多少的平方 static final int tableSizeFor(int cap){ int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1); return (n < 0) ? 1 : (n >= MAXIMU_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; } //其中numberOfLeadingZeros方法,采用了从大到小进行判断 public static int numberOfLeadingZeros(int i){ if(i <= 0){ return i == 0 ? 32 : 0; } int n = 31; if(i >= 1 << 16) {n -= 16; i >>>= 16;} if(i >= 1 << 8) {n -= 8; i >>>= 8;} if(i >= 1 << 4) {n -= 4; i >>>= 4;} if(i >= 1 << 2) {n -= 2; i>>>= 2;} return n - (i >>> 1); } //初始化HashMap public HashMap(int initialCapacity, float loadFactor){ if(initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity:" + initialCapacity); if(initialCapacity > MAXIMUM_CAPACITY){ initalCapacity = MAXIMUM_CAPACITY; } if(loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor); this.loadFactor = loadFactor; this.threshlod = tableSizeFor(initialCapacity); } //获取特定key的value值 public V get(Object key){ Node<K,V> e; return (e = getNode(hash(key),key)) == null ? null : e.value; } //通过hash、key获取Node final Node<K,V> getNode(int hash, Object key){ Node<K,V>[] tab; Node<K,V> first, e; int n; K k; //先判断数组是否是非空 if((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n-1) & hash]) != null){ if(first.hash == hash && //总是先检查第一个结点 ((k = first.key) == key || (key != null && key.equals(k)))) return first; } //如果不是第一个结点,则判断是否有下一个结点,接着需要判断是链表形式的还是红黑树型的 if((e = first.next) != null){ if(first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash,key); do{ if(e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; }while((e = e.next)!=null);//进行循环,一直比对hash、key是否相等 } return null; } //利用getNode进行判断 public boolean containsKey(Object key){return getNode(hash(key),key) != null;} //put--(key,value) public V put(K key, V value){ return putVal(hash(key),key,value,false,true); } //重点来看看putVal final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict){ //建立临时数组、临时结点 Node<K,V>[] tab; Node<K,V> p;int n,i; if((tab = table) == null || (n = tab.length) == 0)//如果此时table数据为空,进行扩容 n = (tab = resize()).length; if((p = tab[i = (n - 1)&hash]) == null) //若找到下标,此时没有值,即为null,则创建结点 tab[i] = newNode(hash,key,value,null); else{//否则将将进行遍历链表 Node<K,V> e; K k; //先检查头结点,如果hash,key相等,则已经插入了该结点 if(p.hash == hash && ((k = e.key) == key) || (key != null && key.equals(k))) e = p; //判断插入的结点p是否是树结点 else if(p isinstanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeval(this,tab,hash,key,value); else{ for(int binCount = 0;;++binCount){ if((e = p.next) == null){ p.next = newNode(hash,key,value,null); //如果binCount>=7时,链表树化为红黑树 if(binCount >= TREEIFY_THRESHOLD - 1) treeifyBin(tab,hash); break; }//找到相等的结点,直接break if(e.hash == hash && ((k = e.key) == key ||(key != null && key.equals(k)))) break; //移动链表指针,指向下一个结点 p = e; } } if(e != null){//存在映射关系,但是value为空 V oldValue = e.value; if(!onlyIfAbsent || oldValue == value) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if(++size > threshold) resize(); afterNodeInsertion(evict); return null; } final Node<K,V>[] resize(){ //定义oldTab,oldThr Node<K,V>[] oldTab = table; int oldCap = (oldTab == null) ? 0:oldTab.length; int oldThr = threshold; int newCap, newThr = 0;//新的容量、新的阈值 //进行判断 if(oldCap > 0){ //直接把阈值设置为最大值,返回原来的数组 if(oldCap >= MAXIMUM_CAPACITY){ threshold = Integer.MAX_VALUE; return oldTab; }//容量放大两倍,阈值也放大两倍 else if((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFALUT_INITIAL_CAPACITY) newThr = oldThr << 1; // 阈值放大两倍 } //此时,oldCap等于零,但是阈值oldThr大于零,直接用oldThr进行替换 else if(oldThr > 0) newCap = oldThr;//用thre替换初始容量 else {//此时,oldCap和oldThr都为零,进行初始值替换,表明第一次扩容 newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACOR * DEFAULT_INITIAL) } //初始化阈值newThr,初始化threshold if(newThr == 0){ float ft = (float)newCap * loadFactor; newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY)?(int)ft : Integer.MAX_VALUE; } threshold = newThr; //建立Node型数组,对table进行赋值 Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; table = newTab; //将oldTab中元素赋值给newTab if(oldTab != null){ for(int j = 0;j < oldCap; ++j){ Node<K,V> e; if((e = oldTab[j]) != null){ oldTab[j] = null;//释放旧的数组中的内存 if(e.next == null) //判断原来数组位置是否只有一个节点,则进行赋值 newTab[e.hash & (newCap - 1)] = e; else if (e instanceof TreeNode)//判断是树节点 ((TreeNode<K,V>)e).split(this,newTab, j,oldCap); else{ //rehash,高位等于索引+oldCap,即:j + oldCap; Node<K,V> loHead = null, loTail = null; Node<K,V> hiHead = null, hiTail = null; Node<K,V> next; do{ next = e.next; if((e.hash & oldCap) == 0){ //表明是原来的位置,看这个地方是否有头结点,若无直接赋值,否则从尾部插入 if(loTail == null) loHead = e; else loTail.next = e; loTail = e; }//表明需要从新hash到新的位置,同理如上 else{ if(hiTail == null) hiHead = e; else hiTail.next = e; hiTail = e; } }while((e = next) != null); if(loTail != null){ //先建立一个链表,之后将这个链表接到j索引处 loTail.next = null; newTab[j] = loHead; } // 同理只是更改了索引位置:j + hiHead if(hiTail != null){ hiTail.next = null; newTab[j + oldCap] = hiHead; } } } } } return newTab; } public V remove(Object key){ Node<K,V> e; return (e = removeNode(hash(key),key,null,false,true)) == null ? null : e.value; } final Node<K,V> removeNode(int hash, Object key,Object value, boolean matchValue,boolean movable){ //定义临时变量 Node<K,V>[] tab; Node<K,V> p; int n, index; if((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null){ Node<K,V> node = null, e; K k; V v; //若是头结点 if(p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) node = p; //往下遍历 else if((e = p.next) != null){ if(p instanceof TreeNode)//是树形节点 node = ((TreeNode<K,V>) p).getTreeNode(hash,key); else { do {//进行循环遍历,找到即跳出循环 if(e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))){ node = e; break; } p = e; } while((e = e.next) != null); } } if(node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))){ if(node instanceof TreeNode) ((TreeNode<K,V>)node).removeTreeNode(this,tab,movale); //若判断是头结点,直接去掉头结点,接在后面 else if(node == p) tab[index] = node.next; else p.next = node.next;//在链表中间,跳过该节点 ++modCount; --size; afterNodeRemoval(node); return node; } } return null; }}
2020年11月02日
14 阅读
0 评论
0 点赞
2020-10-15
位逻辑运算符
位逻辑运算符位逻辑运算符包含 4 个:&(与)、|(或)、~(非)和 ^(异或)。除了 ~(即位取反)为单目运算符外,其余都为双目运算符。表 1 中列出了它们的基本用法。运算符含义实例结果&按位进行与运算(AND)4 & 54\ 按位进行或运算(OR)4 \55^按位进行异或运算(XOR)4 ^ 51~按位进行取反运算(NOT)~ 4-5位与运算符位与运算符为&,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0。例如下面的表达式:100&0图 1 所示为这个运算过程,结果为 0。图 1 100位与0的运算过程下面是两个非零的数字进行位与运算的过程。int x = 5,y = 12; // 创建整型变量保存两个数int z = x&y; // 对这两个数进行位与运算,结果保存到z这两行语句执行后变量 Z 的值是 4,图 2 所示为这个运算过程。图 2 5位与12的运算过程位或运算符位或运算符为|,其运算规则是:参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1;如果对应的二进制位都为 0,结果才为 0。下面是一个使用位或运算符的表达式。11|7运算结果为 15,图 3 所示为其运算过程。图 3 11位或7的运算过程位异或运算符位异或运算符为^,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。下面是一个使用位异或运算符的表达式。11^7运算结果为 12,图 4 所示为其运算过程。图 4 11位异或7的运算过程提示:在有的高级语言中,将运算符^作为求幂运算符,要注意区分。位取反运算符位取反运算符为~,其运算规则是:只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。下面是一个使用位取反运算符的表达式。~10运算结果为 65525,图 5 所示为其运算过程。图 5 对10位取反的运算过程我们可以使用如下的程序来检查这个运算结果。int i = 10;System.out.printf("%d \n",~i);编译执行以上程序,会发现输出的结果是 -11,而不是 65525。这是因为取反之后的结果是十六进制数,而在上面的程序中使用 %d 将输出转换为了十进制数。可以使用如下语句查看十六进制结果。int i=10;System.out.printf("%x \n",~i);可以看到输出结果为 fff5,将它转换为二进制是 1111111111110101。这个二进制数的最高位为 1,表示这个数为负数。除最高位外,按位取反再加 1,即得到二进制原码 1000000000001011,用十进制数表示即为 -11。注意:位运算符的操作数只能是整型或者字符型数据以及它们的变体,不用于 float、double 或者 long 等复杂的数据类型。位移运算符位移运算符用来将操作数向某个方向(向左或者右)移动指定的二进制位数。表 2 列出了 Java 语言中的两个位移运算符,它们都属于双目运算符。运算符含义实例结果»右移位运算符8»14«左移位运算符9«236左位移运算符左移位运算符为«,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。例如,将整数 11 向左位移 1 位的过程如图 6 所示。图 6 对11左移1位运算过程从图 6 中可以看到,原来数的所有二进制位都向左移动 1 位。原来位于左边的最高位 0 被移出舍弃,再向尾部追加 0 补位。最终到的结果是 22,相当于原来数的 2 倍。右位移运算符右位移运算符为»,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。例如,将整数 11 向右位移 1 位的过程如图 7 所示。图 7 对11右移1位运算过程从图 7 中可以看到,原来数的所有二进制位都向右移动 1 位。原来位于右边的最低位 1 被移出舍弃,再向最高位追加 0 补位。最终到的结果是 5,相当于原数整除 2 的结果。复合位赋值运算符所有的二进制位运算符都有一种将赋值与位运算组合在一起的简写形式。复合位赋值运算符由赋值运算符与位逻辑运算符和位移运算符组合而成。表 3 列出了组合后的复合位赋值运算符。运算符含义实例结果&=按位与赋值num1 &= num2等价于 num 1=num 1 & num2\=按位或赋值num1 \= num2等价于 num 1=num 1 \num2^=按位异或赋值num1 ^= num2等价于 num 1=num 1 ^ num2-=按位取反赋值num1 ~= num2等价于 num 1=num 1 ~ num2«=按位左移赋值num1 «= num2等价于 num 1=num 1 « num2»=按位右移赋值num1 »= num2等价于 num 1=num 1 » num2
2020年10月15日
18 阅读
0 评论
0 点赞
2020-10-15
Java 抛错记录
抛错ArithmeticException 算数异常Infinity 无穷大 例如两个浮点数相除NaN 不是一个数字 例如浮点型 0/0 整数型0/0报错NullPointerException 空指针异常
2020年10月15日
21 阅读
0 评论
0 点赞
2020-10-15
Day 10 String方法
Day 10定位 str.charAt(index); 给脚标求数值给脚标 找数值 str.substring(index); 从脚标去截断 取出他和他后边的数值str.substring(a,b); a到b 包含a 不包含bstr.indexOf("a",1); 找出a字符 从第一个开始找str.replace("原有字符串","新字符串") 替换字符串str.toUpperCase() 字符全部变大写str.toLowerCase 字符全部变小写String[] agiao = str.split(" ") 截断双引号里边填写需要替换的字符 scanner.hasNextLine(); 判断是否有下一行 用于while(ture){}str.subSequence(a,b); a 第几行 b一行打印多少个str.contains(a) 包含a //定位1:知到脚标找值 char a = str.charAt(3); String strSub = str.substring(1,2); //定位2;知到值找脚标 int c = str1.indexOf("a",1); //从后边往前找 2表示从后边第几个开始找 int f = str1.lastIndexOf("c", 2);
2020年10月15日
22 阅读
0 评论
0 点赞
2020-10-15
Day9 面向对象
Day9 面向对象封装 继承 多态方法名符合小驼峰命名java对于文件的管理package(default) 包 默认 任何类型都能访问 public 公开 只有同包类型可以访问private 私有 只有自己可见无参构造 初始化自定义类型String 字符串常量池 定位 str.charAt(index); 给脚标求数值给脚标 找数值 str.substring(index); 从脚标去截断 取出他和他后边的数值str.substring(a,b); a到b 包含a 不包含bstr.indexOf("a",1); 找出a字符 从第一个开始找
2020年10月15日
22 阅读
0 评论
0 点赞
1
...
11
12
13
...
16