java基础-02

目录

1、String StringBuffer StringBuilder

2、字节流、字符流

3、异常

4、集合

5、线程


1、String StringBuffer StringBuilder

        这三个类都是以char[]的形式保存的字符串,但是String类型的字符串是不可变的,对String类型的字符串做修改操作都是相当于重新创建对象。而对 StringBuffer 和 StringBuilder 进行增删操作都是对同一个对象做操作。StringBuffer 中的方法大部分都使用 synchronized 关键字修饰,所以 StringBuffer 是线程安全的。StringBuilder 中的方法则没有,线程不安全,但是 StringBuilder 因为没有使用使用 synchronized 关键字修饰,所以性能更高,在单线程环境下我会选择使用StringBuilder,多线程环境下使用 StringBuffer。如果生成的这个字符串几乎不做修改操作,那么我就直接使用 String,因为不调用 new 关键字声明 String 类型的变量的话它不会在堆内存中创建对象,直接指向 String 的常量池,并且可以复用.效率更高。

String的部分方法:

charAt()获取下标对应值

concat()拼接字符串

endsWith()以...结尾?

StartsWith()以...开始?

equals()内容是否相等已重写

hashCode()哈希值码

IndexOf()第一次出现...的下标

lastIndexOf()最后一次出现...的下标

IsEmpty()是否为空

length()长度

replace(1,3)用3取代1

subString()下标开头的子串

subString(1,3)下标1到3的子串

toLowerCase()转换成小写

toUpperCase()转换成小写

trim()去掉两端空格

split()以...分割

matches()是否匹配

valueOf()转换成字符串类型

getBytes()把每个字符转换成码值,存入byte[]

toCharArray()把字符串里的字符存入char[]


2、字节流、字符流

字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。

        字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。
        字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。详见文末效率对比。

2.1 InputStream抽象类
        此抽象类是表示字节输入流的所有类的超类/抽象类,不可创建对象哦

常用方法:
        abstract int read()从输入流中读取数据的下一个字节
        int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
        int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组,off表示存时的偏移量
        void close() 关闭此输入流并释放与该流关联的所有系统资源

2.2 FileInputStream子类
        直接插在文件上,直接读取文件数据

 创建对象
        FileInputStream(File file)—直接传文件对象
        通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定FileInputStream(String pathname)—传路径通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定

2.3 BufferedInputStream子类
        BufferedInputStream 为另一个输入流添加一些功能,在创建BufferedInputStream 时,会创建一个内部缓冲区数组(默认8k大小)。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。

创建对象
        BufferedInputStream(InputStream in)
        创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

https://blog.csdn.net/weixin_43884234/article/details/116952152

来自 程序媛 泡泡


3、异常

用来封装错误信息的对象

异常的处理方式:捕获和抛出

异常之后的代码不会执行

异常:
1、Throwable下有个异常子类:error和execption。
        Error:是不能靠程序能处理的,比如:内存溢出。
        Exception:运行时异常(非检查异常)和非运行时异常(检查异常)
2、常见的运行时异常:控制台出现
        1)    NullPointerException(空指针异常)当操作一个空引用抛出的一个异常
        2)    NumberFormatException(数据格式化异常)试图将字符串转换为一种数值类型时,但字符串转换不适当出现的异常。
        3) ClassCastException(类型转换异常)强制类型转换不匹配时出现的异常。
        4) ArrayIndexOutOfBoundsExveption(数组下标越界异常):当使用一个不存在的下标时出现的异常。
        5) ArithmeticException(数字异常):异常运算条件时出现的
非运行时异常:需要抛出的异常
        1)SQLException:访问数据库时出现的
        2)IOException :当发生某种I/O异常时抛出的
        3)ClassNotFoundException:当应用程序使用Class类中的forName方法、loadClass方法时,抛出的异常。
3、在JAVA语言中,如何引发异常?对异常处理的途径?
在java中可以使用throw来引发异常。
        1)使用throws抛出异常,
        2)使用try-catch语句捕获异常。
(当调用一个含有throws声明异常抛出的方法时,编译器要求必须处理这个异常,而处理方式有两种:
 1:使用try-catch处理该异常
 2:在当前方法上继续声明throws将该异常 抛出


4、集合

        Collection 接口是集合类的根接口,java 中没有提供这个接口的直接的实现类。但是却让其被继承产生了两个接口就是 Set 和 List。Set 中不能包含重复的元素。List 是一个有序的集合,提供了按索引访问的方式。

        Map是Java.util 包中的另一个接口,它和 Collection 接口没有关系,是互相独立的,但是都属于集合类的一部分。Map包含了 Key-value 对。Map不能包含重复的 Key,但是可以包含相同的value。

4.1 List(有序,可重复)

        List 里存放的对象是有序的,同时也是可以重复的,List 关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往 list 集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。

ArrayList 和 LinkedList

        ArrayList 和 LinkedList 在用法上没有区别,但是在功能上还是有区别的。LinkedList 经常用在增删操作较多而查询操作很少的情况下,ArrayList 则相反。

        List 接口:元素按进入先后有序保存,可重复

        ArrayList接口实现类,数组,随机访问,没有同步,线程不安全

        LinkedList接口实现类,链表,插入删除,没有同步,线程不安全

        Vector 接口实现类数组,同步,线程安全(Stack 是 Vector 类的实现类)

4.2 Set(无序,不能重复)

        Set 里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。

        HashSet集合:底层数据结构是哈希表(是一个元素为链表的数组),不能保证元素的顺序。HashSet 不是线程同步的,如果多线程操作 HashSet 集合,则应通过代码来保证其同步。集合元素值可以是 null。影响哈希冲突的条件,首先看哈希值是否相等,然后判断 equals 是否相等(内容是否相等)

TreeSet集合

        A:底层数据结构是红黑树(是一个自平衡的二叉树)

        B:保证元素的排序方式(自然排序),实现 Comparable 接口

LinkedHashSet 集合

        A::底层数据结构由哈希表和链表组成。

        原来存储是什么顺序,就是什么顺序

        Set 接口: 仅接收一次,不可重复,并做内部排序

        HashSet 使用 hash 表(数组)存储元素

        LinkedHashSet 链表维护元素的插入次序

        TreeSet 底层实现为二叉树,元素排好序

4.3 Map(键值对,建唯一,值不唯一)

        Map 集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对 map 集合遍历时先得到键的 set 集合,对 set 集合进行遍历,得到相应的值。

实现类:HashMap、Hashtable、LinkedHashMap 和 TreeMap

HashMap

        HashMap 是最常用的 Map,它根据键的 HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。因为键对象不可以重复,所以 HashMap 最多只允许一条记录的键为 Null,允许多条记录的值为 Null,是非同步的。

Hashtable

        Hashtable 与 HashMap 类似,是 HashMap 的线程安全版,它支持线程的同步,即任一时刻只有一个线程能写 Hashtable,因此也导致了 Hashtale 在写入时会比较慢,它继承自Dictionary 类,不同的是它不允许记录的键或者值为 null,同时效率较低。

ConcurrentHashMap

        线程安全,并且锁分离。ConcurrentHashMap 内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的 hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

LinkedHashMap

        LinkedHashMap 保存了记录的插入顺序,在用 Iteraor 遍历 LinkedHashMap 时,先得到的记录肯定是先插入的,在遍历的时候会比 HashMap 慢,HashMap 的全部特性。

TreeMap

        TreeMap 实现 SortMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。不允许 key 值为空,非同步的;


5、线程

5.1进程

5.1.1 概念

        就是正在运行的程序。也就是代表了程序锁占用的内存区域。

5.1.2  特点

        独立性:进程是系统中独立存在的实体,它可以拥有自己的独立的资源,每一个进程都拥有自己私有的地址空间。在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间。

        动态性:进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。在进程中加入了时间的概念,进程具有自己的生命周期和各种不同的状态,这些概念在程序中都是不具备的。

        并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会互相影响。

5.2 线程

5.2.1  概念

        线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程可以开启多个线程。多线程扩展了多进程的概念,使得同一个进程可以同时并发处理多个任务。简而言之,一个程序运行后至少一个进程,一个进程里包含多个线程。如果一个进程只有一个线程,这种程序被称为单线程。如果一个进程中有多条执行路径被称为多线程程序。

5.2.2  进程和线程的关系

                一个进程中可以有多个线程,每个进程有自己独立的内存,每个线程共享一个进程中的内存,每个线程又有自己独立的内存。(记清这个关系,非常重要!)

    所以想使用线程技术,得先有进程,进程的创建是OS创建的,你能实现吗?不能,一般都是c或者c++语言完成的。

5.3  多线程的特性

5.3.1  随机性

5.3.2  线程状态

        1)   新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

        2)   就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

        3)   运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

        4)   阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态;

        5)   根据阻塞产生的原因不同,阻塞状态又可以分为三种:

                a)   等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

                b)   同步阻塞:线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

                c)   其他阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

        6)   死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

5.3.3     创建线程的方式

        我们常说的方式有以下三种:继承 Thread 实现 Runable 接口 实现 Callable 接口(可以获取线程执行之后的返回值)但实际后两种,更准确的理解是创建了一个可执行的任务,要采用多线程的方式执行,还需要通过创建 Thread 对象来执行,比如 new Thread(new Runnable(){}).start();这样的方式来执行。在实际开发中,我们通常采用线程池的方式来完成 Thread 的创建,更好管理线程资源。

5.4  同步锁

        把有可能出现问题的代码包起来,一次只让一个线程执行。通过sychronized关键字实现同步。当多个对象操作共享数据时,可以使用同步锁解决线程安全问题。

5.4.1  synchronized

  特点:

        ①. 前提1,同步需要两个或者两个以上的线程。

        ②. 前提2,多个线程间必须使用同一个锁。

        ③. 同步的缺点是会降低程序的执行效率,  为了保证线程安全,必须牺牲性能。

        ④. 可以修饰方法称为同步方法,使用的锁对象是this。

        ⑤. 可以修饰代码块称为同步代码块,锁对象可以任意。

5.5  线程锁

5.5.1  悲观锁和乐观锁

        悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了。

        乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。

5.5.2  两种常见的锁

Synchronized 互斥锁(悲观锁,有罪假设)

        采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,防止打断原子操作。每个对象的锁只能分配给一个线程,因此叫做互斥锁。

ReentrantReadWriteLock 读写锁(乐观锁,无罪假设)

        ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,实际上独占锁是一种相对比较保守的锁策略,在这种情况下任何“读/读”、“读/写”、“写/写”操作都不能同时发生,这在一定程度上降低了吞吐量。然而读操作之间不存在数据竞争问题,如果”读/读”操作能够以共享锁的方式进行,那会进一步提升性能。因此引入了ReentrantReadWriteLock,顾名思义,ReentrantReadWriteLock是Reentrant(可重入)Read(读)Write(写)Lock(锁),我们下面称它为读写锁。

        读写锁内部又分为读锁和写锁,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。读锁和写锁分离从而提升程序性能,读写锁主要应用于读多写少的场景。

5.6  设计模式

5.6.1  概念

        单例模式可以说是大多数开发人员在实际中使用最多的,常见的Spring默认创建的bean就是单例模式的。

        单例模式有很多好处,比如可节约系统内存空间,控制资源的使用。其中单例模式最重要的是确保对象只有一个。简单来说,保证一个类在内存中的对象就一个。

5.6.2  饿汉式

package cn.tedu.design;

//测试单例设计模式--就是按照一定的开发步骤,按照一定的模板进行开发,达到程序中只会有一个实例在干活的目的!!

public class Test5_Design {

    public static void main(String[] args) {

       //4,测试 new多少次都是一个对象???--

//     MySingleTon m = new MySingleTon();--构造方法私有化

       MySingleTon m1 = MySingleTon.getMy();

       MySingleTon m2 = MySingleTon.getMy();

       System.out.println(m1==m2);//是同一个对象吗???

       System.out.println(m1.equals(m2));//默认用Object的==

    }

}

class MySingleTon {

    //1,私有化改造方法  -- 目的就是控制外界创建对象的权利

    private MySingleTon() {}

    //2,封装创建好的对象   -- 封装,不让外界随意看到我创建的对象

    static private MySingleTon my = new MySingleTon();

    //3,提供公的获取对象的方法

    //静态方法,因为没法new了,还想用,就用类名访问--修饰成静态的

    static public MySingleTon getMy(){

       return my;//静态只能调静态

    }

}

5.6.3  懒汉式

//懒汉式 -- 面试重点!!延迟加载思想+线程不安全

class MySingleTon2 {

    // 1,私有化改造方法 -- 目的就是控制外界创建对象的权利

    private MySingleTon2() {

    }

    // 2,封装创建好的对象 -- 先不创建对象,啥时候用啥时候创建!!

    static private MySingleTon2 my;

    // 3,提供公的获取对象的方法

    // 静态方法,因为没法new了,还想用,就用类名访问--修饰成静态的

    synchronized static public MySingleTon2 getMy() {//b,方法里都是同步代码,可以是同步方法

//     synchronized (MySingleTon2.class) {//a,同步代码块,静态方法的锁,是类名.class本类的字节码对象

           // t1,t2,t3来准备new

           if (my == null) {

              // t1 new

              // t2 new

              // t3 new

              my = new MySingleTon2();// 开始创建!! 延迟加载

           }

//     }

       return my;// 静态只能调静态

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值