【Java8】堆栈/队列/数组/链表/红黑树,List/set子接口,hashcode/hashset,Map/内部接口,/统计字符个数,debug,斗地主,Collections,TreeSet
文章目录
- 1.堆栈/队列/数组/链表:数据结构即计算机组织管理数据的方式,堆栈指的是内存图中的栈,不是堆
- 2.红黑树:二查,二查平,二查平1倍
- 3.List子接口:集合,IndexOutOfBoundsException
- 4.ArrayList的扩容原理:Stringbuild默认长度=16,扩容2倍
- 5.LinkedList:push堆栈
- 6.set子接口:单例=keySet
- 7.Object类的hashcode方法:对象的真正的内存地址(无限种)->哈希码 (43亿不到的可能)。极端下多个明文 -> 同一密文 (哈希碰撞)。打印对象,.toString(),.hashCode()
- 8.String类的hashcode方法:a97,碰撞
- 9.哈希表(HashSet)原理:元素不重复
- 10.linkedHashset和Hashset区别:A a = new A(){},coll.iterator().hasNext()
- 11.Map:Map和Collection是并列关系,Map.Entry < Integer,String > 是数据类型
- 12.内部接口:除了Inner访问受限于Outer,这两各自独立
- 13.统计字符出现个数:.containsKey(.charAt)
- 14.debug:断点/单点/高级调试
- 14.1 单步调试:over,into,out
- 14.1.1 step over
- 14.1.2 step into
- 14.1.3 Force step into
- 14.1.4 step out
- 14.1.5 Drop frame
- 15.2 高级调试:
- 15.2.1 跨断点调试
- 15.2.2 查看断点
- 15.2.3 设置变量值
- 16.斗地主:list.addAll(set)
- 17.Collections类和TreeSet:return o1-o2是升序
- 17.1 自定义MyCollections类来模拟完成addAll()和sort()方法
1.堆栈/队列/数组/链表:数据结构即计算机组织管理数据的方式,堆栈指的是内存图中的栈,不是堆
如下查询慢:知道张三在哪,不能马上知道王五在哪,挨个查。如下增删虽然不用整个动(如删除李四,只需要将箭头指向王五就行),但是还是要先查找到再删除
,效率还是慢。但是直接删除张三或马六头尾元素快。
2.红黑树:二查,二查平,二查平1倍
二叉树
:每个节点最多两个子节点。查找树
:左小右大(二分法)。平衡树
:左右尽量相等(一边的节点层次不会超过另一边的两倍)。二查平1倍
:红黑树(数组和链表折中方案)。
二叉搜索树BST(二查)
:插入或查询一节点时,树的每一行只需要和这一行的一个节点比较(因为左小右大),复杂度完全依赖树深度。树的行数即高度=logn【n为节点总数,2的树行数次方为n】,BST读和写的复杂度都为logn。
有序数组
:查找时用二分查找法(和BST像),时间复杂度也为logn。有序数组查询最差情况logn,而当BST为单边时(最差情况),BST查询和插入都为o(n)。为什么很多情况下用BST,而不是有序数组二分查找?因为有序数组查找用二分查找logn,但是插入(不是查)要移动,插入时间复杂度为o(n)。
BST很少在语言内部数据结构存储里用(因为下面直线情况),自平衡二叉树AVL(二查平)
是BST(二查)
的继承优化:左子树和右子树都是平衡二叉树,而且左子树和右子树深度之差绝对值不会超过1(左旋和右旋),AVL读和写的复杂度最差情况都为O(logn)。
AVL平衡左右子树相差1,这个条件很苛刻,导致很多情况下都不满足这个平衡条件,需要旋转变换,变换的话需要浪费时间。红黑树(二平查1倍)
平衡条件更加宽松些左右深度差一倍
即> = 节点数相同,< = 节点数差一倍(因为红节点的子节点
必须为黑即黑红相间)。叶子节点(最后一个)和null节点都为黑节点
这样宽松条件导致我们在插入节点时候变化更少的,所以红黑树写的性能会高一些,所以treemap/hashmap底层采用红黑树(BST会变直线,AVL左右只能差1)。
如下是红黑树的插入变色
流程:最上面根节点必须为黑,插入节点(为叶子节点)必为红节点(看插入节点的父节点和父节点的兄弟节点即叔节点)。null节点算叶子节点即黑节点
,当前插入的003是爷爷节点001
的右右。
如下左旋+变色。
3.List子接口:集合,IndexOutOfBoundsException
package com.itheima01.list;
import java.util.ArrayList;
import java.util.List;
/*Collection子接口:List1. List的特点:重索序1. 有先后顺序:元素存储的顺序和取出的顺序相同2. 具有整数索引,就是下标3. 允许重复元素2. List的方法(带索引)(List特有的,共有的在Collection讲过)1. add(int index, E element) :往索引位置添加一个元素1. Java中的 三个越界异常1. IndexOutOfBoundsException 集合2. ArrayIndexOutOfBoundsException 数组3. StringIndexOutOfBoundsException 字符串越界2. get(int index):获取指定索引的元素3. remove(int index):移除指定索引的元素4. set(int index, E element) :修改指定索引的元素值
*/
public class ListDemo {public static void main(String[] args) {// add();List<String> list = new ArrayList<>();list.add("周楠");list.add("王凤枝");list.add("王凯");String s = list.get(2);System.out.println(s); //王凯list.remove(2);System.out.println(list); //[周楠, 王凤枝]list.set(1,"昌老师");System.out.println(list); //[周楠, 昌老师]}//11111111111111111111111111111111111111111111111111111111111111111111111111111private static void add() {List<String> list = new ArrayList<>();list.add("周楠");list.add("王凤枝");list.add("王凯");/*add(int index, element)往指定索引位添加元素index = list.size()IndexOutOfBoundsException: : 索引越界异常*/list.add(3,"田锁"); //不越界,4越界System.out.println(list);String[] array = {};//System.out.println(array[0]); //ArrayIndexOutOfBoundsException : 数组索引越界String str = "abc"; // 字符串底层也是数组// char c = str.charAt(3); //索引0,1,2 // System.out.println(c); //StringIndexOutOfBoundsException:字符串索引越界}
}
4.ArrayList的扩容原理:Stringbuild默认长度=16,扩容2倍
ArrayList底层是存Object数组,扩容新建一个长度为原来1.5倍新数组(空)。
如下10进制的4就是2进制的0100(8421),3/2=1,ArrayList.java源码中出现左右移(二进制右移一位相当于十进制/2)
。
package com.itheima01.list;
import java.util.ArrayList;
/*
* ArrayList: 数组
* 1. 最常用: 适合 查询需求比较多的场景
* 2. 原理: ArrayList扩容原理
* ArrayList底层是数组,数组长度不可变,为什么ArrayList又可变呢? 因为数据迁移
*/
public class ArrayListDemo {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("xx");System.out.println(3 >> 1); // 1 //除2取整System.out.println(4 >> 1); // 2System.out.println(10 >> 1); // 5System.out.println(3 << 2); //12 //3*2*2,左移2位}
}
5.LinkedList:push堆栈
package com.itheima01.list;
import java.util.LinkedList;
/*LinkedList特点1. 底层数据结构: 双向链表2. 查询速度慢,增删快(增删需求多而且增删首尾用LinkedList)3. 特有方法(不能使用多态,父类不能调子类特有方法)1. addFirst 元素添加在链表开头2. addLast(add相同) 元素添加在链表结尾3. getFirst 获取链表开头4. getLast 获取链表结尾5. removeFirst 移除并返回链表开头6. removeLast 移除并返回链表结尾//下面两个不需要掌握7. pop 从此列表所表示的堆栈处弹出一个元素(最顶部元素弹出,removeFirst)8. push 将元素推入此列表所表示的堆栈(元素存储到集合顶部,addFirst)
*/
public class LinkedListDemo {public static void main(String[] args) {// method01();LinkedList<String> list = new LinkedList<>();list.add("张三"); // 是链表,不是按堆栈结构添加元素list.add("李四");list.add("王五");// 链表 -> 堆栈 ,张三在栈顶
// String pop = list.pop(); // 弹栈: 栈顶元素()
// String removeFirst = list.removeFirst();//效果同上
// System.out.println(pop);list.push("王二"); //栈顶添加,效果等同于addSystem.out.println(list);}private static void method01() {LinkedList<String> list = new LinkedList<>();list.add("张三");list.add("李四");list.add("王五");list.addFirst("王二");list.addLast("马六");System.out.println(list);String first = list.getFirst();String last = list.getLast();System.out.println(first + "," + last);System.out.println(list);list.removeFirst();list.removeLast();System.out.println(list);}
}
6.set子接口:单例=keySet
package com.itheima02.set;
import java.util.HashSet;
import java.util.Set;public class SetDemo {public static void main(String[] args) {Set<String> set = new HashSet<>();set.add("张三");set.add("李四");boolean result = set.add("王五");System.out.println(result); //true boolean result2 = set.add("王五");System.out.println(result2); //false //元素不可重复System.out.println(set);//[李四,张三,王五] //存取不保证顺序}
}
7.Object类的hashcode方法:对象的真正的内存地址(无限种)->哈希码 (43亿不到的可能)。极端下多个明文 -> 同一密文 (哈希碰撞)。打印对象,.toString(),.hashCode()
package com.itheima03.hash;
/*
* Object类有一个方法: int hashCode() : 返回该对象的哈希码值。
* 1. 原理: 将对象的真正的内存地址(明文) 进行 哈希算法 加密之后产生的 哈希码值(密文)
* 2. 加密 :
* 明文 : 大家都看的懂东西 I love you
* 密文 : 明文经过加密算法变成密文 J mpwf zpv
* 加密算法: 数学 (凯撒加密: 字母按字母表右移动一位)
* 破解: 频率分析法 (e i -> d h),截获大量数据进行大数据分析e,i出现频率最高,密文中出现最多的是d,h
*
* 哈希算法: 公开
* 基本保证 一个明文 -> 一个密文 不同明文不同的密文
* 告诉你算法,告诉你密文, 算不出明文
*
* 3. 源码: public native int hashCode(); 本地方法
* native(本地关键字) 修饰的方法没有java方法体 (方法实现在JVM底层, 用C语言写的)
* 返回值 int (43亿不到的可能)
*/
public class HashcodeDemo {public static void main(String[] args) {Person p = new Person();System.out.println(p); //com.itheima03.hash.Person@14ae5a5// return getClass().getName() + "@" + Integer.toHexString(hashCode());System.out.println(p.toString());//com.itheima03.hash.Person@14ae5a5 // 上面两个打印结果都一样 // 如下内存地址: 16进制哈希码值14ae5a5 和下面10进制相等System.out.println(p.hashCode()); // 10进制: 21685669}
}
class Person{}
8.String类的hashcode方法:a97,碰撞
String s1 = “abc”,如下h就是hash值
(只看最后一个h),b是98,c是99。
package com.itheima03.hash;
// String类重写了Object的hashcode方法 (31算法)
public class StringHashCodeDemo {public static void main(String[] args) {String s1 = "abc";String s2 = "acD";String s3 = "重地";String s4 = "通话";System.out.println(s1.hashCode());//96354System.out.println(s2.hashCode());//96354 //和上面哈希碰撞System.out.println(s3.hashCode()); //1179395System.out.println(s4.hashCode()); //1179395}
}
9.哈希表(HashSet)原理:元素不重复
hashcode(密文)为HashSet(HashSet底层数据结构是hash表)做铺垫。如下三个abc字符串都为96354。问题:HashSet如何判定这个元素是否跟已存在的元素是重复即如下[重地,通话,abc,acD]?Set不存重复元素。S3因为是new出来的,和S1,S2明文即真正的内存地址不一样。
下面S1,S4,S5,S6都是不重复元素。竖:暗文或暗文%16同(因为数组长度为16
),equal不一样。横:明文和暗文和equal都不一样。HashSet是效率最高的set且元素不重复,同一链表(竖)hashcode一样,但是链表如果太长查询慢,所以假如同一hash值(hashcode)碰撞了8次,链表重构为红黑树
。
同一链表上都hash碰撞,数组的第一个位置余数=0,第二个位置余数=1。。。16的容量为什么到16*0.75=12
就扩容了?再哈希rehash(余数重新算)这段时间内,16没满,我还有的用,如果rehash非常快就不用提前。
package com.itheima02.set;
import java.util.HashSet;
import java.util.Objects;
/*
* HashSet: 判定重复元素:(明文地址【内】,hash值【外】,equals【名字】)。
* 内同-》重复不插, 内不同 外不同 默认e不同-》横插, 内不同 外同 e不同-》竖插
*
* person类父类的Object: 1. hashcode:明文内存地址加密得到密文hash值
*(不同明文产生不同密文,刘亦菲明文即两个内存地址不一样,密文hash值基本不会相同,万一碰撞了,还有下面2进 行保障)
* 2. equals == 比较真正内存地址
*
* 需求: 两个对象就算地址不同, 但是所有属性一一相同, 就认为是同一元素
* 解决: 重写hashcode和equals方法 -> 类中的所有属性,重写规范见文章:https://blog.csdn.net/weixin_43435675/article/details/112604089
*/
public class HashSetDemo02 {public static void main(String[] args) {HashSet<Person> set = new HashSet<>();set.add(new Person("高圆圆",18));set.add(new Person("刘亦菲",19));set.add(new Person("刘亦菲",19));//Person类继承Object类,new新地址System.out.println(set); }
}
class Person{String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object o) { //alt+insert选equals()and hashCode() //每个属性一一比对if (this == o) return true;if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; //o是外部传入,转成personreturn age == person.age &&Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age); //工具类Objects.java中hash方法中hashCode方法就是31算法,也是逐一遍历}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
没有重写Person类的hashcode和equals方法。
如下重写…如下就是hash表的应用:元素不重复,效率高。
10.linkedHashset和Hashset区别:A a = new A(){},coll.iterator().hasNext()
package com.itheima00.question;
import java.util.HashSet;
import java.util.LinkedHashSet;
/*
* Set: 不保证 存入和取出顺序一致
* HashSet : 无序
* LinkedHashSet : 多个另一个链表, 来记录存入的顺序,有序即取出有序,所以效率变低(少用)
*/
public class Demo01 {public static void main(String[] args) {HashSet<String> set = new LinkedHashSet<>(); //向上转型set.add("张三");set.add("李四");set.add("王五");set.add("马六");System.out.println(set); //打印出有序的,LinkedHashSet不同于HashSet }
}
package com.itheima00.question;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class Demo02 {public static void main(String[] args) {Collection<String> coll = new ArrayList<String>(); //Collection是接口coll.add("张三");coll.add("张三2");coll.add("张三3"); // Iterator接口类型 变量 = 其实现类对象 (多态的向上转型)/* Iterator<String> it = coll.iterator(); //Collection即coll是接口,接口调用方法执行子类ArrayList重写的iterator()while(it.hasNext()){String name = it.next();System.out.println(name); //张三 张三2 张三3}*/// while(coll.iterator().hasNext()){ //不能这样把it换了链式编程,原因如下图
// String name = coll.iterator().next();
// System.out.println(name);
// }}//11111111111111111111111111111111111111111111111111111111111111111111111111111111111111public static void method01(){MyClass mc = new MyClass();A a = mc.test(); //右边返回必然是A接口实现类对象即向上转型,不需要new //上行等同于Iterator<String> it = coll.iterator(); 不一定需要看到new A a2 = new A() { //java中对象不一定看到new才放心 //new一个实现接口的匿名内部类A,使用{}具体实现接口 @Overridepublic void show() {}} ;}
}
interface A{void show();
}
class MyClass{public A test(){ //返回A接口,不写void
// A a = new A(){}; //匿名内部类
// return a;return new A() { //下面等同于上面两行,return A接口的子类对象@Overridepublic void show() {}};}
}
11.Map:Map和Collection是并列关系,Map.Entry < Integer,String > 是数据类型
package com.itheima01.map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/*Map中的方法1. Map<K,V> <泛型>: K 表示作为键的类型,V表示值的类型2. put: 存储键值对1. 键值对存储到集合中 V put (K,V)2. 如果存储了相同的键,覆盖原有的值3. 返回值:一般返回null,如果存储了重复的键,返回被覆盖之前的值3. get:通过键,取出键对应的值1. V get(K),传递键,返回对应的值2. 如果集合中没有这个键,返回null4. remove:移除键值对1. V remove(K),传递键,移除这个键值对2. 返回值:移除之前的值(无此键,则返回null)5. keySet: 将集合中所有的键,存储到Set集合中6. entrySet:获取到Map集合中所有的键值对存入Set接中7. size:获取map集合的大小
* Map:
* 1. key不可以重复
* 2. value可以重复
* 如果key存在,那么新value覆盖旧value
*/
public class MapDemo {public static void main(String[] args) {Map<Integer,String> map = new HashMap<>();map.put(1,"张三");map.put(2,"李四");map.put(3,"王五");map.put(4,"王五");map.put(3,"马六"); //覆盖王五System.out.println(map);//{1=张三,2=李四,3=马六,4=王五}String name = map.get(5); //null,不是越界异常,无索引String name = map.get(3); //从key获取valueSystem.out.println(name);//马六//根据key删除key-valuemap.remove(3);System.out.println(map);System.out.println(map.size()); //3,几个k}
}
如下key不可重复,所以放到set集合(单例)。如下两种遍历方式都涉及set:
package com.itheima01.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MapLoopDemo01 { //loop循环public static void main(String[] args) {Map<Integer,String> map = new HashMap<>();map.put(1,"张三");map.put(2,"李四");map.put(3,"王五"); Set<Integer> keySet = map.keySet(); //1.把key这一列取出来放到set集合中 for (Integer key : keySet) { //2.遍历这个set集合,取出每个key。keySet.for回车 String value = map.get(key); //3. 根据key获取valueSystem.out.println(key + "->" + value);}}
}
package com.itheima01.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MapLoopDemo02 {public static void main(String[] args) {Map<Integer,String> map = new HashMap<>();map.put(1,"张三");map.put(2,"李四");map.put(3,"王五");Set<Map.Entry<Integer,String>> entrySet = map.entrySet(); // 1. 把map转化成 Set<Entry> setfor(Map.Entry<Integer,String> entry : entrySet){ // 2. 遍历这样的set, 取出每个entry//Entry是Map的内部接口,Map有很多Entry,Entry相当于Map属性一样。Map.是接口名直接调用//如果import java.util.Map.Entry,则Map.Entry可换成Entry Integer key = entry.getKey(); //3. 从这个键值对中,取键,再取值String value = entry.getValue();System.out.println(key + "--" + value);}}
}
package com.itheima03.impl;
import java.util.*;
/*
* HashMap是最常用的map实现类,因为快。
* 1. key不可以重复,但是value可以重复
* 2. key如何判定重复? 先判断hashcode ,再判断equals
* Object: hashcode 和 equals 跟对象真正地址有关
* 重写了hashcode 和 equals,张三山东 覆盖 张三山西 新覆盖旧
*/
public class HashMapDemo {public static void main(String[] args) {// method01();
// method02(); //较method01交换了k和vnew LinkedHashSet<>(); //点进源码,底层是LinkedHashMapnew TreeSet<>(); //TreeMapnew HashSet<>(); //HashMap//如下有序存取LinkedHashMap<Person,String> map = new LinkedHashMap<>();map.put(new Person("张三",18),"山西");map.put(new Person("吴彦祖",20),"福州");map.put(new Person("李四",19),"广东");
// map.put(new Person("张三",18),"山东");Set<Person> keySet = map.keySet();for (Person key : keySet) {String value = map.get(key);System.out.println(key + "---" + value);}}private static void method02() {HashMap<Person,String> map = new HashMap<>();map.put(new Person("张三",18),"山西"); //key=Person 自定义类型map.put(new Person("吴彦祖",20),"福州");map.put(new Person("李四",19),"广东");map.put(new Person("张三",18),"山东"); //new出来地址不同Set<Person> keySet = map.keySet();for (Person key : keySet) {String value = map.get(key);System.out.println(key + "---" + value);}// HashSet<Object> set = new HashSet<>(); //点进HashSet看源码
//HashSet【collection接口】的底层是HashMap【Map接口】 ,只不过hashset只使用了HashMap key这一列,value这一列不用}private static void method01() { HashMap<String, Person> map = new HashMap<>();map.put("1号",new Person("张三",18)); //value=Person 自定义类型map.put("2号",new Person("李四",19));map.put("3号",new Person("李四",19));map.put("1号",new Person("王五",20)); //System.out.println(map);Set<Map.Entry<String,Person>> entrySet = map.entrySet();for (Map.Entry<String, Person> entry : entrySet) {String key = entry.getKey();Person value = entry.getValue();System.out.println(key + "-" + value);}}
}class Person{String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age &&Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}
如下吴彦祖应该在第二个,存取无序,解决:HashMap换成LinkedHashMap。
12.内部接口:除了Inner访问受限于Outer,这两各自独立
package com.itheima02.inner;
import java.lang.reflect.Field;
import java.util.Date;
import com.itheima02.inner.Outer.Inner;
/*
* inner class : 访问受限, 受限于外部类
* 有两个包是不用导入:1. java.lang (String,Object)
* 2. 当前类所在的包
* 1和2的子包都要导(如内部接口就在当前包的子包下)
*/
public class InnerDemo {public static void main(String[] args) {// new Date()new String("");new Object();
// new Field(); //java.lang包的子包,要导包}
}//1111111111111111111111111111111111111111111111111111111111111111111111111111111111111
interface Outer{//public static final //因为Outer是接口,所以不能实例化,只能接口.。所以final让I变为常量,static让I可用接口名.直接调用int I = 1;//public abstractvoid outerMethod();//new外部类对象不需要new内部类对象,同理实现Outer接口不需要实现Inner接口//public static //外部接口不能创建实例来调用,所以接口名调用,所以静态。上面Map.Entry即外接口.内接口(Entry是Map的内接口)interface Inner{ void innerMethod();}
}
class A implements Outer{ //不需要实现Inner@Overridepublic void outerMethod() {}
}
class B implements Outer.Inner{@Overridepublic void innerMethod() {}
}
class C implements Outer,Inner{//上面导过包了,Inner不用写成Outer.Inner@Overridepublic void outerMethod() {}@Overridepublic void innerMethod() {}
}
13.统计字符出现个数:.containsKey(.charAt)
统计字符串中:大小写字母及数字字符个数:https://blog.csdn.net/weixin_43435675/article/details/107434867
package com.itheima03.impl;
import java.util.HashMap;
/*
* 需求: 计算一个字符串中每个字符出现次数。
* 0. 弄一个Map : 记录 字符=次数 (就像画正字选票)
* char int
* 1. 遍历这个字符串,取出每个字符
* 2. 判断Map中是否存在这个字符-> boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。
* 3. 有: 在对应的次数+1 。没有 : 字符char=1 存进去
*/
public class CountDemo {public static void main(String[] args) {String str = "abcaba"; HashMap<Character, Integer> map = new HashMap<>();//泛型不接收基本类型,所以char写成Character,int的包装类Integerfor(int i=0; i<str.length();i++){char c = str.charAt(i); //相应索引访问到相应字符boolean result = map.containsKey(c); //一开始map为空,下面依次写进去if(result){ // 存在,次数value+1Integer value = map.get(c); //c是key即char
// value = value + 1;
// map.put(c,value);// value++;
// map.put(c,value);// int count = ++value;
// map.put(c,count);map.put(c,++value); //不能写成map.put(c,value++);}else{ // 不存在, 存入c=1map.put(c,1);}}System.out.println(map);}
}
14.debug:断点/单点/高级调试
先设断点再点击如下进入调试。
红色的箭头指向的是现在调试程序停留的代码行:方法 f2() 中,程序的第11行
。红色箭头悬停的区域是程序的方法调用栈区。在这个区域中显示了程序执行到断点处所调用过的所有方法
,越下面的方法被调用的越早。
14.1 单步调试:over,into,out
14.1.1 step over
点击红色箭头指向的按钮,程序向下执行一行(如果当前行有方法调用
,这个方法将被执行完毕返回,然后到下一行)。
14.1.2 step into
点击红色箭头指向的按钮,程序向下执行一行。如果该行有自定义方法,则运行进入自定义方法(不会进入官方类库的方法)。具体步骤如下:在自定义方法发f1()处设置断点,执行调试。
点击如下。
14.1.3 Force step into
该按钮在调试的时候能进入任何方法。
14.1.4 step out
如果在调试的时候你进入了一个方法(如f2()),并觉得该方法没有问题,你就可以使用stepout跳出该方法,返回到该方法被调用处的下一行语句。值得注意的是,该方法已执行完毕。
14.1.5 Drop frame
点击该按钮后,你将返回到当前方法的调用处(如上图,程序会回到main()中)重新执行,并且所有上下文变量的值也回到那个时候。只要调用链中还有上级方法,可以跳到其中的任何一个方法。
15.2 高级调试:
15.2.1 跨断点调试
设置多个断点,开启调试。想移动到下一个断点,点击如下图:
程序将运行一个断点到下一个断点之间需要执行的代码。如果后面代码没有断点,再次点击该按钮将会执行完程序。
15.2.2 查看断点
点击箭头指向的按钮,可以查看你曾经设置过的断点并可设置断点的一些属性。
箭头1指向的是你曾经设置过的断点,箭头2可以设置条件断点(满足某个条件的时候,暂停程序的执行,如 c==97)。结束调试后,应该在箭头1处把所设的断点删除(选择要删除的断点后,点击上方的红色减号)。
15.2.3 设置变量值
调试开始后,在红箭头指向的区域可以给指定的变量赋值(鼠标左键选择变量,右键弹出菜单选择setValue…)。这个功能可以更加快速的检测你的条件语句和循环语句。
16.斗地主:list.addAll(set)
package com.itheima04.Poker;
import java.util.ArrayList;
import java.util.Collections;
// 写一个规则: 2 > A > K > Q > J ...(不行,组合方式太多2也要>K) //上次写的没有排序 //黑红梅方
public class SortDemo {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>(); //重索序list.add(3);list.add(5);list.add(4);list.add(1);list.add(2);System.out.println(list); //[3,5,4,1,2],有序Collections.sort(list);System.out.println(list);//[1,2,3,4,5]}
}
15发给第一个,13发给第二个。。。
package com.itheima04.Poker;
import java.util.*;class PokerDemo {public static void main(String[] args) { HashMap<Integer, String> map = new HashMap<>(); //key=编号, value=牌面String[] colors = {"♠","♥","♣","♦"};String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};int index=0;for (String number : numbers) {//数字写外面,外一次内一周,数字3和4种花拼接,并index标号依次从0对应到3,好按标号排序。 for (String color : colors) {String poker = color + number;map.put(index,poker);index++;}}
// System.out.println(map); //{0=黑桃3,1=红心3,2=梅花3,...}map.put(52,"小☺");map.put(53,"大☺"); Set<Integer> set = map.keySet(); //0-53ArrayList<Integer> list = new ArrayList<>();list.addAll(set); //将set集合中每个元素都放进list中//下面等同于上面 /*for (int i = 0; i < 54; i++) { //0-53编号放进去list.add(i);}*///洗牌Collections.shuffle(list); //只能洗list集合//发牌ArrayList<Integer> p1 = new ArrayList<>();ArrayList<Integer> p2 = new ArrayList<>();ArrayList<Integer> p3 = new ArrayList<>();ArrayList<Integer> dp = new ArrayList<>();for (int i = 0; i < list.size(); i++) { //list里全是编号Integer number = list.get(i);int mod = i % 3;if(i < 3){dp.add(number);}else if(mod == 1){p1.add(number);}else if(mod == 2){p2.add(number);}else if(mod == 0){p3.add(number);}}//排序(Integer:从小到大)Collections.sort(p1);Collections.sort(p2);Collections.sort(p3);Collections.sort(dp);
// lookPoker(map,p1); //因为list即p里都是编号,所以还需要map
// lookPoker(map,p2);
// lookPoker(map,p3);
// lookPoker(map,dp);lookPoker(map,p1,p2,p3,dp);}private static void lookPoker(HashMap<Integer, String> map, ArrayList<Integer>... lists) { //lists为数组名for (ArrayList<Integer> list : lists) {for (Integer number : list) { String poker = map.get(number); //从map中根据number 取出 pokerSystem.out.print(poker + "\t");}System.out.println();}}
// private static void lookPoker(HashMap<Integer,String> map,ArrayList<Integer> list){// for(Integer number : list){// String poker = map.get(number);
// System.out.print(poker+"\t");
// }
// System.out.println();
// }
}
17.Collections类和TreeSet:return o1-o2是升序
package com.itheima05.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/*Arrays数组工具类, Objects对象工具类(命名规则最后+s)- java.utils.Collections是集合工具类,用来对集合进行操作。 常用方法如下:
- public static void shuffle(List<?> list):打乱集合顺序。
- public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
- public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。
*/
public class CollectionsDemo01 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>(); //Integer源码实现了Comparable接口 Collections.addAll(list,5,3,2,4,1); //System.out.println(list); //[3,4,5,1,2]// Collections.sort(list); // 默认: 升序// 如下第二个参数类型是Comparator接口,必须传入接口实现类对象:new Comparator...后面全是匿名内部类Collections.sort(list, new Comparator<Integer>() { // 自定义升降序规则 , 任何排序都是两两比较 @Overridepublic int compare(Integer o1, Integer o2) {// return o1 - o2;//升序: 从小到大return o2 - o1;//降序: 从大到小}});System.out.println(list);}
}
17.1 自定义MyCollections类来模拟完成addAll()和sort()方法
package com.itheima05.collections;
import java.util.ArrayList;
import java.util.Comparator;public class MyCollections { // 1. addAll方法public static void addAll(ArrayList<Integer> list, Integer... args){for (Integer arg : args) {list.add(arg);}}//2. sort方法: 这里采用冒泡排序。collections底层实际是Timsort排序。//注意: 第二个参数是接口,必须传入接口实现类(这将形成多态: 父接口引用调用方法执行的是子类重写方法)public static void sort(ArrayList<Integer> list, Comparator<Integer> comparator) {int temp;for (int i = 0; i < list.size() - 1; i++) {for (int j = 0; j < list.size() - i - 1; j++) { int result = comparator.compare(list.get(j + 1), list.get(j));//j+1和j相邻比较,父类接口调用方法执行子类重写的方法即MyCollections.sort(list, new Comparator<Integer>() {子类重写的方法})。if(result < 0){ //子类重写方法中rerurn o1-o2保证result<0即o1后小,rerurn o2-o1保证result<0即o1后大。temp = list.get(j); //交换list.set(j, list.get(j + 1));list.set(j+1,temp);}}}}
}
package com.itheima05.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;public class CollectionsDemo02 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list,5,3,2,4,1);MyCollections.sort(list, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o1 - o2;}});System.out.println(list);}
}
package com.itheima05.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.TreeSet;public class CollectionsDemo03 {public static void main(String[] args) {ArrayList<Student> list = new ArrayList<>(); //ArrayList底层就是数组,数组和集合差不多。list.add(new Student("张三",20));list.add(new Student("李四",18));list.add(new Student("王五",22));/* Collections.sort(list, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.age - o2.age; //按年龄升序}});System.out.println(list);*///1111111111111111111111111111111111111111111111111111111111111111111111111111111111111 // sort(list) : 这个方法要求集合元素类型需要实现 Comparable接口 (Integer已实现,自定义类型必须手动实现)
// Collections.sort(list); //如果就写class Student不实现Comparable接口,这行会报错
// System.out.println(list);//111111111111111111111111111111111111111111111111111111111111111111111111111111111111 TreeSet<Student> set = new TreeSet<>(); //TreeSet判定元素重复的原理:compare方法 : 两数相减=0(不是hashcode和equals) //TreeSet底层红黑树(红黑树就是排序,左小右大),和哈希表无关,和Collections.sort一样必须实现Comparable接口//Set重点是hashset,TreeSet底层和比较器完全一样,TreeSet具备排序功能但效率不如hashset。TreeMap的key和TreeSet底层一样set.add(new Student("张三",20));set.add(new Student("李四",18));set.add(new Student("王五",22));set.add(new Student("马六",22)); //添不进去,因为compareTo比较的是age,不重复System.out.println(set);}
}//11111111111111111111111111111111111111111111111111111111111111111111111111111111111111
class Student implements Comparable<Student>{String name;int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';} @Overridepublic int compareTo(Student o) {return this.age - o.age; //升序,// this = o1,o = o2 }
}
【Java8】堆栈/队列/数组/链表/红黑树,List/set子接口,hashcode/hashset,Map/内部接口,/统计字符个数,debug,斗地主,Collections,TreeSet相关推荐
- 常见的数据结构:栈 队列 数组 链表 红黑树——List集合 _ HashSet集合、可变参数 collections集合 Map集合
2021-06-07复习java 一.常见的数据结构 栈(先进后出) 队列 数组 链表 红黑树 二.List集合_介绍&常用方法 ArrayList集合 Linkedlist集合 三.Hash ...
- Java集合常见数据结构-栈/队列/数组/链表/红黑树
数组 链表 红黑树
- 存数组元素的个数_HashMap1.8之后为什么要采用数组+链表+红黑树的储存方式?
HashMap概述 HashMap是基于Map接口实现的,采取(key,value)的储存方式.其中key和value可以为空,但是key不能重复.下面我们来详细解读一下HashMap的底层实现原理. ...
- Java--敲重点!JDK1.8 HashMap特性及底层数组+单链表+红黑树知识(建议收藏)
❤️大家好,我是贾斯汀!❤️ 学习目录 学习背景 HashMap特性 HashMap添加元素四步曲 前奏:HashMap如何添加一个元素? 第一步曲:根据key得到hashCode值 第二步曲:根 ...
- HashMap 实现原理及源码解析(jdk8 底层⽤的是数组+链表/红⿊树)
本文会通过HashMap中的put方法为入口,进行源码解读,文章较长,需要耐心阅读 说明 /** */: 代表注释,区别于例子注释 egx::代表例子注释 解读前须知 源码主要关注4⼤点: 确定哈希桶 ...
- 算法高级(26)-在Java8中为什么要使用红黑树来实现的HashMap?
一.前言 在jdk1.8版本后,Java对HashMap做了改进,在链表长度大于8的时候,将后面的数据存在红黑树中,以加快检索速度. 二.红黑树回顾 红黑树的英文是"Red-Black Tr ...
- 常见数据结构-栈-队列-数组-链表-哈希表
数据结构 数据结构是计算机存储.组织数据的方式.是指相互之间存在一种或多种特定关系的数据元素的集合 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率 持续更新,学一个记一个- 栈 ...
- 对于一个采用字符数组存放的字符串str,设计一个递归算法StrLength(char *str)求其字符个数(长度)。递归求字符串长度
递归求字符串长度,需要的就是将数组看成指针,一步一步走下去 int StrLength(char *str) {char *p=str;if(*p=='\0') return 0;else{retur ...
- Java笔记整理五(Iterator接口,泛型,常见数据结构(栈,队列,数组,链表,红黑树,集合),jdk新特性,异常,多线程,Lambda表达式)
Java笔记整理五 1.1Iterator接口 Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象 ...
最新文章
- 【温故知新】CSS学习笔记(样式表)
- java计数循环及小技巧
- Zoom的Web客户端与WebRTC有何不同?
- 计算机通信事业单位专业知识点,事业单位计算机专业知识招考大纲
- linux 内存越界判断_虚拟内存 和 page fault 的解释
- ae saber插件_【AE插件】 用于做动画制作/设计的五个免费插件 非常好用
- docker的php教程https,Docker搭建php环境教程详解
- android版本下载地址 http,Android ADT下载地址(含各版本)
- 瓦楞机自动排单技术收藏
- 电脑重装系统后c盘数据能恢复吗?
- 樊登读书会终身成长读后感_《终身成长》读书笔记
- tableViewCell、collectionViewCell、组头组尾等总结
- 面试阿里被问的哑口无言,原来我……
- Python有道智云API图片文字识别
- 【LOJ2867】「IOI2018」高速公路收费
- 杭州软件测试人员工资水平,杭州软件测试工资待遇如何?
- 为什么电脑浏览器显示时钟快了_xp打开网页提示“你的时钟慢了”的原因及解决方法...
- swift 代码加载xib storyboard
- 2022中国数据库产业排行榜
- 图谱实战 | 华农夏静波:深层语义知识图谱在药物重定位中的应用
热门文章
- YUV与RGB互转各种公式 (YUV与RGB的转换公式有很多种,请注意区别!!!)
- DataUml Design 教程6-DataUML Design 1.1版本号正式公布(支持PD数据模型)
- Wix学习整理(2)——HelloWorld安装添加UI
- 我的.net程序在linux上运行起啦
- 16、Windows API 服务
- db2 两个结构相同的表_从两个工作表提取数据记录,并显示相同记录的报告
- 每日程序C语言25-查找100以内的素数
- 台式电脑怎么连接手机热点_电脑搜不到手机热点 为什么搜不到手机热点
- Java黑皮书课后题第7章:*7.30(模式识别:四个连续相等的数)编写下面的方法,测试某数组是否有四个连续相同值的数。编写测试程序,提示用户输入一个整数列表,调用方法看是否有4个连续且相等的数
- Java黑皮书课后题第3章:**3.22(几何:点是否在圆内)编写程序,提示用户输入一个点(x,y),然后检查这个点是否在以(0,0)为圆心、半径为10的圆内