A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© 卞建彬 中级黑马   /  2018-9-20 15:42  /  621 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

刘亚雄:
List.Set.数据结构.COllections一.数据结构栈:特点:先进后出(FILO,First In Last Out)
入口出口在一侧
栈适用场景:
​        栈内存:(main方法先进栈调用,main方法中其他方法都调用完毕后,main才能出栈)
​        反转内容:(车尾变车头)
队列:特点:先进先出
入口出口在两侧
数组:特点:查询快,增删慢
查询快:数组的地址是连续的,我们通过数组的地址值可以找到数组,通过数组的索引可以快速查找某一元素
增删慢:数组的长度是固定的,我们想要增加/删除一个元素,必须创建一个新数组,把源数组的数据复制过来.
链表:特点:查询慢,增删快
查询慢:链表中的地址不是连续的,每次查询元素都必须从头开始查询
增删快:链表结构,增加/删除一个元素,对链表的整体结构没有影响,所以增删快.
链表中的每一个元素也称之为一个节点,一个节点包含了一个数据源(存储数组),两个指针域(存储地址).
单链表:数据<->下一个节点的地址
单向链表:链表中只有一条链子,不能保证元素的顺序(存储和去除元素的顺序可能不一致)
双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合.
红黑树特点:   趋近于平衡树,查询速度非常快,查询叶子节点最大次数和最小次数不能超过2倍
使用场景:查询和增删都有,需要元素自动排序的场景
约束:
​        1.节点可以是红色的或者黑色的
​        2.根节点是黑色的
​        3.叶子节点(空节点)是黑色的
​        4.每个红色的节点的子节点都是黑色的
​        5.任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同.
树的遍历:往左走

返回当前节点的值

往右走

返回上一层节点
二叉树:分支不能超过两个
排序树/查找树:在二叉树的基础上,元素有大小顺序的,左子树小,右子树大
平衡树:左孩子和右孩子相等
不平衡树:左孩子和右孩子不相等
List集合特点:
​        1.有序的集合,存储元素和取出元素的顺序是一致的.
​        2.有索引,包含了一些带索引的方法
​        3.允许存储重复的元素
list接口中带索引的方法(特有):
  • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
  • public E get(int index):返回集合中指定位置的元素。
  • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素

ArrayList集合
​     ArrayList集合数据存储的结构是数组结构,元素增删慢,查找快.线程不安全,效率高.
适用于查询多,增删少的场景
LinkedList集合
LinkedList集合数据存储的结构是链表结构,查询慢,增删快.
线程不安全,效率高
此集合包含了大量操作首位的方法.
下列方法了解即可:
  • public void addFirst(E e):将指定元素插入此列表的开头。
  • public void addLast(E e):将指定元素添加到此列表的结尾。
  • public void push(E e):将元素推入此列表所表示的堆栈。相当于addFirst
  • public E getFirst():返回此列表的第一个元素。
  • public E getLast():返回此列表的最后一个元素。
  • public E removeFirst():移除并返回此列表的第一个元素。
  • public E removeLast():移除并返回此列表的最后一个元素。
  • public E pop():从此列表所表示的堆栈处弹出一个元素。相当于removeFirst
  • public boolean isEmpty():如果列表不包含元素,则返回true。

Vertor集合
集合数据存储的结构是数组结构,
特点: 查询慢,增删快,线程安全,效率低
set接口
特点:
​        1.不允许存储重复的元素
​        2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
HashSet
(implements set)
特点:
​        1.不允许存储重复的元素
​        2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历
​        3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
​        4.底层是一个哈希表结构(查询速度非常的快)
哈希值:
​        是一个十进制的整数,由系统随机给出(就是对象的地址值)
native int hashCode();
"重地"与"通话"的哈希值一样(值一样叫做哈希冲突)
HashSet集合存储数据的结构(哈希表):
​        jdk1.8之前:哈希表=数组+链表
​        jdk1.8之后:哈希表=数组+链表
或者                    哈希表=数组+红黑树(提高查询的速度)
哈希表的特点:速度快
数组结构:把元素进行了分组(相同哈希值的元素是一组).
链表/红黑树结构把相同哈希值的元素连接到一起
如果链表的长度超过了8位,那么就会把链表转换为红黑树(提高查询速度)
HashSet存储自定义类型元素:
set集合保证元素唯一:
​       储存的元素(String,Integer....Student.Person..).必须重写hashCode方法和equals方法
要求:同名 同年龄的人,视为同一个人,只能储存一次.
LinkedHashSet集合:
特点:
底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序.
可变参数
使用前提:当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数
使用格式:定义方法时使用:
​        修饰符 返回值类型 方法名(数据类型...变量名)
可变参数的原理:
​        可以变参数的底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
​        传递参数的个数可以是0个,1,2...多个
注意事项:
​        1.一个方法的参数列表,只能有一个可变参数
​        2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾
终级写法(Object...obj)
Collections
常用功能:
  • public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
  • 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 static <T> void sort(List<T> list使用前提
        被排序的集合里边存储的元素,必须实现Comparable接口,重写接口中的方法compareTo定义排序规则
排序规则:
​        自己-参数:升序
​        参数-自己:降序
Comparator与Comparable区别:
Comparable:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则的compareTo方法
Comparator:相当于找一个第三方的彩票,比较两个
Comparator排序规则:
​        o1-o 2:升序
​        o2-o1:降序
  一. List集合特点
  • 元素存取有序
  • 有索引
  • 元素可以重复

二.常见的数据结构
栈队列数组链表红黑树哈希表 = 数组 + 链表/红黑树
三.数组结构特点
查询快增删慢
四.栈结构特点
先进后出入口出口是同一个
五.队列结构特点
先进先出入口出口在两侧
六.单向链表结构特点
查询慢增删快
栈, 队列
七.Set集合的特点
  • 没有索引
  • 元素不能重复

八.哈希表的特点
哈希表 = 数组 + 链表/红黑树
先调用 hashCode()算出哈希值, 根据哈希值判断数组中是否有重复元素        如果要没有, 就添加        如果有元素, 哈希值冲突                则调用元素的 equals() 遍历 链表/红黑树 依次比较                        如果有重复的, 则不添加                        如果没有重复的, 则添加
九.使用HashSet集合存储自定义元素
去重        重写 hashCode()    重写 equals()
十.说出可变参数的格式
方法名(参数类型... 变量名) {    // 当作数组来使用}
方法名();  // 数组
注意事项:        只能有1个可变参数, 必须放在最后
十一.集合工具类
Collections类        static addAll(Collection c, T... t)    static shuffle(List list)    static sort(List list)    static sort(List list, Comparator c)
十二.能够使用Comparator比较器进行排序
static sort(List list, Comparator c)     传递Comparator实现类对象, 重写 compare(T o1, T o2)     规则:                o1 - o2 升序                o2 - o1 降序
Map双列集合
Map<k,v>
​        K代表键的类型,V代表值的类型  
Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值
Map集合特点
​        1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)键值对
​        2.Map集合中的元素,key和value的数据类型可以相同,也可以不同
​        3.Map集合中的元素,key是不允许重复的,value是可以重复的
​        4.Map集合中的元素,key和value是一一对应的
映射:一对一关系,建和值的对应关系 mapping.
常用类:HashMap<K,V>
​        implements Map<K,V>
​        特点:
​        1.HashMap集合底层是哈希表:查询的速度特别快       
​        jdk1.8之前:数组+单向链表..............................
​        jdk1.8之后:数组+单向链表/红黑树
​        2.HashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致.
LinkedHashMap集合(HashMap的子类)
​        特点:
​        1.LinkedHashMap集合底层是哈希表+链表(保证迭代顺序)
​        2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的.
常用方法
  • public V put(K key, V value):  把指定的键与指定的值添加到Map集合中。
    备注:存储键值对的时候,key不重复,返回值V是null
    ​        存储键值对的时候,key重复,返回值V是被替换的value值.
  • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
  • boolean containsKey(Object key) 判断集合中是否包含指定的键。
  • public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。
  • public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。

Map集合第一种遍历方式:键找值
​        1.使用Map集合的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
​        2.遍历set集合,获取Map集合中的每一个key       
​        3.通过Map集合中的方法get(key),通过key找到value
Map集合第二种遍历方式:使用Entry对象遍历
1.使用Map集合中的方法EntrySet(),把Map集合中的多个Entry对象取出来,存储到一个Set集合中

2.遍历Set集合,获取每一个Entry对象

3.使用Entry对象中的方法getKey()和getValue()获取键与值.
Map.Entry<K,V>:在Map接口中有一个内部接口Entry
​        Entry对象就是一个节点,节点中存储了key和value
  作用:当Map集合一创建,那么就会在Map集合中创建一个Entry对象,用来记录键与值(键值对对象)
LinkedHashMap
extends HashMap
底层原理:哈希表+链表(记录元素顺序)
元素不允许重复,存取有序
Hashtable<k,v>
Hashtable iplements Map<k,v>接口
特点:
Hashtable与HashMap的区别
相同点:底层都是一个哈希表,
​        1.Hashtable是一个线程安全的集合,是单线程集合,速度慢
        而HashMap是一个线程不安全的集合,是多线程的集合,速度快
​        2.HashMap集合可以存储null值,null键
而Hashtable集合,不能存储null值,null键
​        3.Hashtable和Vector集合一样,在jdk1.2之后被(HashMap,ArrayList)取代
​        Hashtable的子类Properties依然活跃
Properties集合是一个唯一和IO流相结合的集合
TreeMap对键排序.与TreeSet类似JDK9对集合添加的优化
​        jdk9的新特性:
​                List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素.
​        static<E>List<E>of(E...elements)
​        使用前提:
​                当集合中存储的元素的个数已经确定了,不在改变时使用
注意:
1.of方法只适用于以上三个接口,不适用于接口的实现类

    2.of方法的返回值是一个不能改变的集合,集合不能再使用add.put方法添加元素,会抛出异常.

    3.Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常.Debug追踪
   又叫(调试bug)
Debug调试程序:
​        可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug.
使用方式:
​        在行号右边,鼠标左键单击,天机断点(每个方法的第一行,哪里有bug添加到哪里)
​        右键,选择Debug执行程序
​        程序就会停留在添加的第一个断点处.
​        F8:逐行执行程序
​        F7:进入到方法中
​        shift+F8:跳出方法
​        F9:跳到下一个断点,如果没有下一个断点,就结束程序
​        ctrl_+F2:退出debug模式,停止程序
​        Console:切换到控制台
Debug调试程序:   

可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug
使用方式:
    在行号的右边,鼠标左键单击,添加断点(每个方法的第一行,哪里有bug添加到哪里)
    右键,选择Debug执行程序
    程序就会停留在添加的第一个断点处
执行程序:
    f8:逐行执行程序
    f7:进入到方法中
    shift+f8:跳出方法
    f9:跳到下一个断点,如果没有下一个断点,那么就结束程序
    ctrl+f2:退出debug模式,停止程序
    Console:切换到控制台
一、请简述Map 的特点。
Map每个元素由键与值两部分组成
Map键不能重复,每个键对应一个值
键和值可以为null
二、说出Entry键值对对象遍历Map集合的原理。
Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map中是一一对应关系,这一对对象又称做Map 中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。
Map.entrySet
遍历获取每一个entry
Entry.getkey
Entry.getvalue
异常,多线程异常:
2中处理异常的方式:
​        1.throws        声名抛出
​        2.try-catch-finally 捕获并处理
异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
​       在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
   java.lang.Throwable:类是Java语言中所有错误或者异常的超类.
​        Exception:编译器异常
​        RuntimeException:运行期异常
​        Error:错误
​                必须修改源代码,程序猜能执行
异常的处理
throw 关键字:
作用:
​        可以使用throw关键字在指定的方法中抛出指定的异常
格式:
​        throw new xxxException("异常产生的原因:")
注意:
​        1.throw关键字必须写在方法的内部
​        2.throw关键字后边new的对象必须是Exception或者是其子类对象
​        3.throw关键字抛出指定的异常对象,我们就必须处理这个异常对象
​                throw关键字后边创建的是RuntimeException或者RuntimeException的子类对象我们可以不处理,默认交给JVM处理
​                若创建的是编译异常,我们就必须处理这个异常,要么throws要么        try..catch

注意:
在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。Objects非空判断(了解)
public static <T> T requireNonNull(T obj):查看指定引用对象不是null。
Objects.requireNonNull(obj,"  ");
声明异常throws
throws关键字:异常处理的第一种方式,交给别人处理.
声明异常格式:

修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{   }  
注意事项:
​       

    1.throws关键字必须写在方法声名出

    2.throws关键字后边声明的异常必须是Exception或者是其子类

    3.方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常

    如果抛出的多个异常对象有字符类关系,那么直接声明父类异常即可.

    4.调用了一个声名抛出异常的方法,我们就必须处理声明的异常.

    要么继续使用throws声明抛出,交给方法调用者处理,最终交给JVM,

    要么try,..catch自己吃力异常
s.endsWith(".txt")判断当前字符串是否以.txt结尾
s.startWith("txt")判断当前字符串是否以txt开头
捕获异常try…catch
格式:try {        // 可能产生异常的代码    } catch (异常类名 变量名) {        // 处理异常的代码        // 一般会将异常信息存储到日志中    }         ...        } catch (异常类名 变量名) {        // 处理异常的代码        // 一般会将异常信息存储到日志中    }
注意:
​        1.try中可能会抛出多个异常对象,那么久科院使用多个catch来处理这些异常对象
​        2.如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try..catch之后的代码.
如果try中没有产生异常,那么就不会执行catch中的异常处理逻辑,执行完try中的代码,继续执行try..catch之后的代码.
Throwable类中定义了一些查看方法:
  • public String getMessage():获取异常的描述信息,原因(提示给用户的时候,就提示错误原因。返回简短描述

  • public String toString():获取异常的类型和异常描述信息(不用)。返回详细消息
  • public void printStackTrace():打印异常的跟踪栈信息并输出到控制台。打印的是最全面的信息
    finally 代码块
    有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
    注意:
    ​        1.finally不能单独使用,必须和try一起使用
    ​        2.finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要资源释放(IO);
    多个异常使用捕获该如何处理?
    ​       
    • 多个异常分别处理。
    • 多个异常一次捕获,多次处理。
    • 多个异常一次捕获一次处理。
      注意事项:
      一个try多个catch,catch里边定义的异常变量,如果有字符类关系,那么子类的异常变量必须写在上面,否则就会报错


  • 运行时异常被抛出可以不处理。即不捕获也不声明抛出。
  • 如果finally有return语句,永远返回finally中的结果,避免该情况.
  • 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
  • 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
    ​    父类异常什么样,子类异常就什么样

自定义异常异常类如何定义:
  • 自定义一个编译期异常: 自定义类 并继承于java.lang.Exception。
  • 自定义一个运行时期的异常类:自定义类 并继承于java.lang.RuntimeException。

格式:
​        public class xxxException extends Exception/RuntimeException{
}
注意:
​        1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
​        2.自定义异常类,必须得继承Exception或者RuntimeException
​        继承Exception:那么自定义的异常类就是一个编译器异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try..catch
​        继承RuntimeException:是一个运行期异常,无需处理,交给虚拟机处理即可.
多线程并发与并行
  • 并发:指两个或多个事件在同一个时间段内发生。(交替)
  • 并行:指两个或多个事件在同一时刻发生(同时)。

进程:一个应用程序在内存中的一次执行过程.
​        每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
线程:
​        线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程,一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
​        简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程
多线程好处:
​        效率高
​        多个线程直接互不影响.
程序>进程>线程
线程调度
​        线程的调度方式:
​        1.分时调度
​                平均占用cpu时间
​        2.抢占式调度
​                根据优先级,若优先级一样随机选择一个线程,
Java使用的为抢占式调度。
创建线程类
​        主线程:执行主(main)方法的线程
​        单线程程序:java程序中只有一个线程
多线程程序的第一种创建方法
​        1.定义类,继承Thread类
​        2.重写run()方法,run方法内部是线程要执行的任务       
​        3.创建Thread子类的对象,
​        4.调用start()方法启动线程
java.lang.Thread类: 表示线程. 实现了Runnable接口
注意:
​         必须调用start()方法来开启线程,不能直接调用run()方法,调用run()会变成单线程.
​        同一个线程对象,不能多吃调用start(0方法.
​        java是抢占式调度,不同线程的代码,执行顺序是随机的.
练习一:异常的体系
问题:
请描述异常的继承体系
请描述你对错误(Error)的理解
请描述你对异常(Expection的理解)
请描述你对运行时异常(RuntimeException)的理解
1.异常继承体系为:
异常的根类是 java.lang.Throwable,其下有两个子类:
java.lang.Error 与 java.util.Exception 。而Exception又分为编译时期异常:checked异常,与运行时期异常:runtime异常。
2.Error:表示不可修复的恶性的错误,只能通过修改代码规避错误的产生,通常是系统级别的,所以很严重。
3.Exception:表示可修复的良性(相对于错误)的异常,异常产生后程序员可以并且应该通过代码的方式纠正,使程序继续运行,是必须要处理的。
4.运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。
throw与throws的区别
1.请描述throw的使用位置,作用是什么?
​        throw关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,它后面的语句都不执行。
2.请描述throws的使用位置,作用是什么?
​        throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在主函数中调用该方法时,如果发生异常,就会将异常对象抛给方法调用处.


public class RunnableImpl implements Runnable {
    // 成员变量创建锁对象, 该锁对象也要所有线程共享唯一一个

Lock lock = new ReentrantLock();

    @Override
    public void run() {
        // 加锁
        lock.lock();
        try {
            // 操作共享变量的代码...
        } finally {
            // 在finally中保证释放锁
            lock.unlock();  
        }
    }
}

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马