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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黑马★涛仔 初级黑马   /  2018-11-20 14:56  /  593 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

四天的笔记
Day - 03
List Set


1.  数据结构

数据结构: 就是数据的存储方式


2. 栈

栈的特点:

1. 先进后出

2. 出入口在同一侧


3. 队列

队列的特点:

1. 先进先出

2. 入口和出口在两端

适用于高并发场景


4. 数组

数组的特点:

1. 查询快

2. 增删慢


5. 链表

链表是由多个节点组成

链表的特点:

1. 查询慢

2.增删快


6. 红黑树

红黑树的特点 :

1. 元素存储过程中就完成了大小排序

2. 查询比链表快, 增删比数组快


7. List集合


file:///C:/Users/%25E7%25A5%259E%25E5%25A5%2587%25E5%25AE%259D%25E8%25B4%259D/AppData/Local/YNote/data/qqED41ADEF79E33AADEEC40B27412B0329/7a130220b55a492dbaa96b23797ae1bc/e78172ef4a2040a7875303e55b20e90a.jpg


List 集合体系的特点 :

1. 元素有序的   (存入和取出的顺序一致)             排序 : 从小到大

2. 元素可重复的

3. 有索引


List子体系中的实现类都具有上述特点

add(int index, E element): 将指定的元素, 添加到该集合中的指定位置上

get(int index): 返回集合中指定位置的元素

remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素

set(int index, E element): 用指定元素替换集合中指定位置的元素


7.1 ArrayList集合的特点

ArrayList底层的数据结构:

数组


ArrayList的特点:

  查询快   

  增删慢   

  线程不安全, 效率高


7.2 LinkedList集合的特点和特有方法

LinkedList底层的数据结构:     

链表


LinkedList的特点:

1. 查询慢

2. 增删快

3.  线程不安全, 效率高


特有方法 :

addFirst(E e): 将指定元素插入此列表的开头

addLast(E e): 将指定元素添加到此列表的结尾

getFirst(): 返回此列表的第一个元素

getLast(): 返回此列表的后一个元素

removeFirst(): 移除并返回此列表的第一个元素

removeLast(): 移除并返回此列表的后一个元素


7.3 Vector集合

Vector底层的数据结构 :  

数组

Vector的特点:

1. 查询慢

2. 增删快


8. Set集合体系


8.1 Set集合

Set集合的特点 :  

1. 元素不可重复

2. 没有索引


8.2 HashSet

HashSet特点 :

1. 元素不可重复

2. 没有索引

3. 元素存取无序

4. 底层采用 哈希表 结构. (查询快)        

    哈希表 = 数组 + 链表或红黑树


8.3 LinkedHashSet

LinkedHashSet集合特点 :

1. 元素存取有序

2. 元素不可重复

3. 没有索引


9. 可变参数

1. 可变参数可以传递的参数个数, 可以是 0个, 1个, 多个   

2. 一个方法的参数列表中, 只能有一个可变参数   

3. 如果方法的参数有多个, 可变参数必须写在参数列表的后


10.  Collections集合工具类

addAll(Collection<? super T> c, T... elements):往集合中添加一些元素

shuffle(List<?> list): 打乱集合顺序

sort(List<T> list): 将集合中元素按照默认规则排序

sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序





Day - 04
Map


1. Map集合

Map特点:

1. 是双列集合, 一个元素包含两个值 (键key, 值value) 键值对   

2. key和value的类型可以相同, 也可以不同   

3. key不允许重复, value可以重复   

4. key和value是一一对应的, 一个键只能对应一个值


2. Map常用子类

1. HashMap

底层哈希表. key存取无序不可重复

2. LinkedHashSet

底层哈希表+链表. key存取有序不可重复


3.Map常用方法

1. put(K key, V value): 添加/修改 键值对.

2. remove(Object key): 根据键删除键值对, 返回被删除元素的值

3. get(Object key): 根据键获取值

4. containsKey(Object key): 判断是否包含指定的键

5. keySet(): 获取Map集合中所有的键, 存储到Set集合中

6. entrySet(): 获取到Map集合中所有的Entry对象的集合(Set集合)


4.Map遍历方式一: keySet()方法实现通过键找值

keySet()遍历步骤 :

1. Map对象调用 keySet() 方法, 获取包含所有key的Set集合   

2. 遍历Set集合, 获取每个key   

3. 通过Map对象调用 get(Object key) 方法根据key获取到value

Map<String, String> map = new HashMap<>();

Set<String> keys = map.keySet();


5. Entry键值对对象介

entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)

getKey(): 获取Entry对象中的键

getValue(): 获取Entry对象中的值


5.1 Map遍历方式2: 通过entrySet()获取Entry对象形式遍历

entrySet()方法遍历Map步骤:

1. Map对象调用 entrySet() 获取包含所有Entry对象的Set集合   

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

3. 调用Entry对象的 getKey() 和 getValue() 方法获取键和值


6. HashMap存储自定义数据类型作为

HashMap存储自定义JavaBean对象作为key保证key唯一不重复, 需要让JavaBean重写 hashCode() 和 equals() 方法


7. LinkedHashMap类

LinkedHashMap底层: 哈希表 + 链表     key不允许重复, 但key存取有序





Day - 05
异常 多线程


1. 异常的概念

异常: 指的是程序在执行过程中, 出现的非正常的情况, 最终会导致JVM的非正常停止


2. 异常的分类

1. 错误(Error): 不能捕捉处理的严重问题, 只能修改代码

2. 异常(Exception): 可以捕获处理的问题

①. 编译时异常:

编译时期就会发生的异常, 必须在编译时期处理

②. 运行时异常:

编译时正常, 运行时才会发生的异常


3. 异常关键字: throw制造异常

1. throw 必须写在方法的内部

2. throw 后面new的异常对象, 必须是 "Exception" 或 "Excetion的子类" 的对象

格式:

throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");


4. 异常的处理方式1: throws声明抛出异常

格式:

修饰符 返回值类型 方法名() throws 异常类名1, 异常类名2,...{   

}

示例 :

public static void readFile(String filename) throws FileNotFoundException


5. 异常的处理方式2: 捕获异常

try...catch : 捕获并处理异常

try {

        // 可能产生异常的代码

    } catch (异常类名 变量名) {

        // 处理异常的代码

        // 一般会将异常信息存储到日志中

    }

注意:

1.  try 中可能会抛出多种异常, 就可以写多个 catch 分别处理每种异常


6. Throwable中的3个异常处理方法

String getMessage(): 异常的信息. 没有原因返回null

String toString(): 异常的类型和原因信息

void printStackTrace(): 使用标准错误输出流打印异常信息

System.out.println(e.getMessage());


7. finally代码块

1. finally 必须和 try...catch 一起使用

2. finally 一般用于释放资源 (IO流时用到)

catch(异常类型 异常变量名) {

        // 处理异常

    } finally {

        // 无论是否发生异常, 是否捕获, 最后都会执行的代码.

        // 通常在这里执行释放资源的操作

    }


8. 自定义异常类

定义编译时异常: 继承 Exception

定义运行时异常: 继承 RuntimeException

为了在抛出异常时, 显示一些提示信息, 我们可以定义2个构造, 一个无参, 一个有String参数

   // 自定义编译时异常

public class RegisterException extends Exception {

        public RegisterException() {

            super();

        }


        public RegisterException(String message) {

            super(message);

        }

    }


9. 多线程

并发: (交替执行) 指两个或多个事件在"同一时间段内"发生

并行: (同时执行) 指两个或多个事件在"同一时刻"发生 (同时发生)


9.1 进程

进程: 一个应用程序在内存中的一次执行过程


9.2 线程

线程: 是进程内的一个独立执行单元 (一条代码执行路径)

        一个程序运行后至少有一个进程, 一个进程中可以包含多个线程


9.3 线程的调度

1. 分时调度: 所有线程轮流使用CPU, 平分占用CPU的时间

2. 抢占式调度: 优先让优先级高的线程使用CPU; 如果优先级相同, 则随机选择一个线程执行


9.4 主线程

主线程:

        我们以前编写的代码, 也在一条线程中执行, 该线程叫作"main线程", 也称  

为"主线程"


9.5 创建多线程程序的第一种方式: 继承Thread类

实现多线程的第一种方式:

        1. 定义类, 继承 Thread 类

        2. 重写 run() 方法, run方法内部是线程要执行的任务

        3. 创建Thread子类的对象, 调用 start() 方法启动线程


void start(): 启动线程, 即让线程开始执行run()方法中的代码

注意:

        必须调用 start() 方法来开启线程, 不能直接调用 run() 方法, 调用 run() 会

变成单线程

        同一个线程对象, 不能多次调用 start() 方法

        Java是抢占式调度, 不同线程的代码, 执行顺序是随机的

       


Day - 06
线程 同步 线程间通信


1. 多线程的内存       

多线程情况下, 每个线程都有各自的栈内存 每个线程各自的方法调用, 进的是各自线程的栈 "栈"是每个线程各自的, "堆"是所有线程共用的


2. Thread常用方法: getName(), currentThread()

getName(): 获取线程的名称

Thread currentThread(): 返回对当前正在执行的线程对象的引用

run(): 用于让子类重写, 表示该线程要执行的任务.不能直接调用

start(): 启动线程, 即让线程开始执行run()方法中的代码


3. 创建多线程程序的方式: 实现Runnable接口

创建多线程的第二种方式:

1. 定义类,实现Runnable接口

2. 重写run( )方法, 要执行的代码

3. 创建Runnable实现类对象

4. 创建Thread类对象,在构造方法中传入Runnable实现类对象

5. 通过Thread对象调用start()方法启动线程


4. Thread 和Runnable的区别

1. 避免单线程的局限性

2. 增强了程序的扩展性, 降低了程序耦合性


5. 匿名内部类方式创建线程

new 父接口/父类() {   

重写方法 };


继承Thread类 实现Runnable接口

  new Thread(new Runnable(){            

@Override            

public void run() {               

// 要执行的任务            

}        

}).start();


6. 线程安全问题

6.1 线程安全问题的原因

问题发生的场景:

多个线程操作共享资源

问题发生的原因:

  JVM是抢占式调度, CPU在每个线程之间切换是随机的, 代码执行到什么位

  置是不确定的   

在操作共享资源时, 由于一个线程还没有执行完, 另一个线程就来操作, 就会

出现问题


6.2 解决线程安全问题方式1: 同步代码块

同步代码块: 使用synchronized关键字修饰的代码块,并传入一个当作锁的对象

格式:

synchronized(锁对象) {

}


6.3 解决线程安全问题方式2: 同步方法

同步方法: 使用synchronized关键字修饰的方法,具有默认的锁对象

非静态同步方法的锁对象: this

public synchronized void method(){        

// 可能会产生线程安全问题的代码     

}


静态同步方法的锁对象: 当前类的字节码对象 Class对象

RunnableImpl.class -> Class对象

获取一个字节码对象的3种方式:

1. 对象名.getClass()

2. 类名.class

3. Class.forName("类的全名")


6.4 解决线程安全问题3: Lock锁

lock(): 获取锁

unlock(): 释放锁

  @Override

public void run() {

// 加锁

lock.lock();

try {            

// 操作共享变量的代码...        

} finally {            

     // 在finally中保证释放锁

lock.unlock();

}


7. 线程间的通信

notify(): 随机唤醒在同一个锁对象上的某一个处于等待状态的线程

notifyAll(): 唤醒所有在同一个锁对象上处于等待状态的线

wait(): 让当前线程处于"无限等待"状态


线程生命周期中, 可以出现有6中状态:

1. NEW                       新建

2. RUNNABLE           可运行

3. BLOCKED             (锁)阻塞

4. WAITING               无限等待

5.TIMED_WAITING   计时等待

6. TERMINATED       终止


8. Object类中wait(long timeout)和notifyAll()方法

wait() 和 sleep() 的区别:

  1. wait会释放锁, 恢复时需要重新获取锁; sleep不会释放锁   

   2. wait可以被notify/notifyAll唤醒; sleep不会   

   3. wait要用锁对象调用; sleep要用Thread类名调用


这就是这四天的笔记,感谢观看,谢谢!




0 个回复

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