Java学习笔记(十)------集合、泛型、Java绘图、Java事件处理机制、线程进程、IO流、Properties类

目录

集合

集合框架体系(重要)

单列集合

双列集合

Collection接口实现类的特点

Collection接口和常用方法 

Collection接口遍历元素方式

使用Iterator(迭代器) 方式

 for循环增强方式

 List接口

 List的三种遍历方式

 ArrayList注意事项

 ArrayList底层结构和源码分析(重要)

Vector底层结构和源码剖析

ArrayList和Vector的比较

 LinkedList底层结构

 ArrayList和LinkedList比较

​编辑

Set接口以及常用方法 

Set接口的常用方法

Set接口的遍历方式

 HashSet

HashSet底层机制

 HashSet扩容和转换成红黑树机制

 LinkedHashSet

 LinkedHashSet底层机制

Map接口

 Map接口实现类的特点(JDK8)

Map接口常用方法 

 Map接口遍历方法

 HashMap

HashMap底层机制及源码剖析 

​编辑

 HashTable

 HashMap和hashTable对比

Properties 

​编辑

总结------开发中如何选择集合实现类

Collection工具类

操作排序 

 泛型

 泛型的好处

泛型的语法

泛型的说明

泛型的实例化 

泛型使用细节

自定义泛型类 

自定义泛型类注意细节 

 自定义泛型接口

自定义泛型接口注意细节

 自定义泛型方法

自定义方法注意细节 

 泛型的继承和通配符

Java绘图

坐标系

像素 

Graphics类

 Java事件处理机制

线程

线程相关概念

程序

进程 

线程

 单线程和多线程

并发和并行 

 创建线程

 线程常用方法

​编辑 用户线程和守护线程

 线程7大状态

线程生命周期 

 线程同步机制

线程同步方法 

 互斥锁 ​​​​编辑

互斥锁的注意事项

线程的死锁 

释放锁

IO流

文件 

文件流 

创建文件的方法

获取文件相关信息

目录操作和删除文件

流的分类 

InputStream字节输入流 

FileReader和FileWriter 

节点流处理流 

 节点流和处理流的区别和联系

对象流

序列化和反序列化 

 对象流的细节

 标准输入输出流

 转换流

 打印流

Properties类 

Properties类常用方法 

集合

可以动态保存任意多个对象。提供了一系列方便操作对象的方法:add、remove、set、get等。使用集合添加,删除元素更简洁

集合框架体系(重要)

集合主要是两组:单列集合和双列集合。

单列集合

双列集合

 

Collection接口实现类的特点

Collection接口和常用方法 

实现子类ArrayList 

Collection接口遍历元素方式
使用Iterator(迭代器) 方式

1.Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。

2.所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。

3.Iterator的结构:

Iterator iterator = 集合.iterator();// 先得到集合对应的迭代器

while(iterator.hasNext()){  // 使用while遍历

        Object obj = iterator.next();

        System.out.println(obj);

}

//当退出while循环后,这时iterator迭代器指向最后的元素。

//如果希望再次遍历,需要重置迭代器。iterator = 集合.iterator();

4.Iterator仅用于遍历集合,Iterator本身并不存放对象。

 for循环增强方式

增强for循环,可以代替iterator迭代器,特点:增强for就是简化版的iterator,(底层仍然是迭代器)本质一样。只能用于遍历集合或数组。(快捷键:I)

基本语法

for(元素类型 元素名:集合名或数组名){

        访问元素

 List接口

 List接口是Collection接口的子接口。

1.List集合类中元素有序(即添加顺序和取出顺序一致),并且可以重复

2.List集合中的每个元素都有其对应的顺序索引即支持索引。(索引从0开始)

3.List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号取容器中的元素。

4.JDK API中List接口的实现类有:Vector、ArrayList、LinkedList等。

5.

 List的三种遍历方式

 ArrayList注意事项

 ArrayList底层结构和源码分析(重要)

Vector底层结构和源码剖析

ArrayList和Vector的比较

 LinkedList底层结构

 ArrayList和LinkedList比较
Set接口以及常用方法 

1.无序(添加和取出的顺序不一致),没有索引。取出的顺序虽然不是添加的顺序,但是取出的顺序固定

2.不允许重复元素,所以最多包含一个null。

3.JDK API中Set接口的实现类有:HashSet、TreeSet等

Set接口的常用方法

和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样。

Set接口的遍历方式

同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。

1.可以使用迭代器。

2.增强for。

3.不能使用索引的方式来获取。

 HashSet

1.HashSet实现了Set接口。 

2.HashSet实际上是HashMap。源码:public HashSet(){ map = new HashMap<>();}

3.可以存放null值,但是只能有一个null

4.HashSet不保证元素是有序的,取决于hash后,再确定索引的结果。(不能保证存放元素的顺序和取出顺序一致)

5.不能有重复的元素/对象。在前面Set接口使用已经讲过。

HashSet底层机制

1.HashSet底层是HashMap,HashMap底层是(数组 +链表+红黑树) 。

2.HashSet的添加元素底层实现(hash() + equals())。

        (1)添加一个元素时,先得到hash值---会转成->索引值。(2)找到存储数据表table,看这个索引位置是否已经存放的有元素。(3)如果没有直接加入。如果有调用equals比较,如果相同,就放弃添加,如果不相同,则添加在最后。(4)在java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TREEFY_CAPACITY(默认64),就会进化树化(红黑树)。

 HashSet扩容和转换成红黑树机制

1.HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFactor)是0.75 = 12.

2.如果table数组使用了临界值 12就会扩容到16 * 2 = 32,新的临界值就是32*0.75 = 24,以此类推。

3.在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制。

 LinkedHashSet

1.LinkedHashSet是HashSet的子类

2. LinkedHashSet底层是一个LinkedHashMap,底层维护了一个 数组+双向链表

3.LinkedHashSet 根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。

4.LinkedHashSet 不允许添加重复元素

 LinkedHashSet底层机制

1.在LinkedHashSet中维护了一个hash表和双向链表(LinkedHashSet有head和tail)。

2.在每一个结点有before和after属性,这样可以形成双向链表。

3.在添加一个元素时,先求hash值,再求索引,确定该元素在table中的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加【原则和hashset一样】)。

示意代码:

tail.next = newElement

newElement.pre = tail

tail = newElement;

4.这样的话,我们遍历LinkedHashSet也能确保插入顺序和遍历顺序一样。 

Map接口

 Map接口实现类的特点(JDK8)

Map接口常用方法 

 Map接口遍历方法

 

 HashMap

HashMap底层机制及源码剖析 

1.(k,v)是一个Node实现了Map.Entry<K,V>,查看HashMap的源码可以看到。

2.jdk7.0的hashmap底层实现[数组+链表],kdk8.0底层[数组+链表+红黑树]。

 HashTable

1.存放的元素是键值对:即K-V。

2.hashtable的键和值都不能为null。否则会抛出NullPointerException。

3.hashTable 是线程安全的,hashMap是线程不安全的。

4.hashTable使用方法基本上和hashMap一样

 HashMap和hashTable对比

Properties 
总结------开发中如何选择集合实现类

Collection工具类

Collections是一个操作Set、List和Map等集合的工具类。

Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作。

操作排序 

 泛型

泛(广泛)型(类型)--> Integer、String、Dog等。

1.泛型又称参数化类型,是jdk5.0出现的新特性,解决数据类型的安全性问题。

2.在类声明或实例化时只要指定好需要的具体类型即可。

3Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。

4.泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值的类型或者是参数类型

 泛型的好处

1.编译时,检查添加的元素的类型,提高了安全性。

2.减少了类型转换的次数,提高效率。

3.不再提示编译警告。 

泛型的语法

泛型的说明

interface 接口<T>{} 和 class 类<K,V>{}

比如:List、ArrayList

说明 :

1.其中T,K,V不代表值,而是表示类型。

2.任意字母都可以。常用T表示,是Type的缩写。

泛型的实例化 

要在类名后面指定类型参数的值(类型)如:

1.List<String> strList = new ArrayList<String>();

2.Iterator<Customer> iterator = customers.iterator(); 

泛型使用细节

1.泛型类型只能是引用类型,不能是基本数据类型。

2.在给泛型制定具体类型后,可以传入该类型或者该类型的子类型

3.泛型使用形式:

List<Integer> list1 = new ArrayList<Integer>();

ArrayList<Integer> list2 = new ArrayList<Integer>();  // 用List来接受

推荐写法:(实际开发中往往简写,编译器会进行类型推断)

ArrayList<Integer> list2 = new ArrayList<>();

4.List list3 = new ArratList();  // 默认给的泛型是[<E> E就是Object]

自定义泛型类 

基本语法:class 类名<T,R....>{   成员   } // T,R泛型标识符,一般为大写单个字母

自定义泛型类注意细节 

1.普通成员可以使用泛型(属性,方法)

2.使用泛型的数组,不能初始化

3.静态方法中不能使用类的泛型。

4.泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)。

5.如果在创建对象时,没有指定类型,默认为Object。 

 自定义泛型接口

 基本语法:interface 接口名<T,R...>{  } 

自定义泛型接口注意细节

1.接口中,静态成员也不能使用泛型

2.泛型接口的类型,在继承接口或实现接口时确定。

3.没有指定类型,默认为Object。 

 自定义泛型方法

基本语法:修饰符 <T,R...>返回类型 方法名(参数列表){  } 

自定义方法注意细节 

1.泛型方法,可以定义在普通类中,也可以定义在泛型类中。

2.当泛型方法被调用时,类型会被编译器确定。

3.Public void eat(E e){}  修饰符后没有<T,R...> eat方法不是泛型方法,而是使用了泛型。 

 泛型的继承和通配符

1.泛型不具备继承性

List<Object> list = new ArrayList<String>(); //错误。泛型布具备继承性。

2.<?>:支持任意类型泛型

3.<? extends A>:支持A类以及A类的子类,规定了泛型的上限

4.<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

Java绘图

坐标系

坐标原点位于左上角,以像素为单位。在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。

像素 

计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的。例如:分辨率为800*600的显示器,表示计算机屏幕上的每一行由800个点组成,共有600个行,整个屏幕共有480 000个像素。像素是一个密度单位,而厘米是长度单位,两者无法比较。 

Graphics类

 实例:在IDEA中画形状,并在控制面板中显示。(见文档Draw.Drawtest) 

控制小球受到键盘的控制,上下左右运动。(见文档Draw.MoveBall

 Java事件处理机制

Java事件处理是采取”委派时间模型“。但事件发生时,产生事件的对象,会把此”信息“传递给”事件的监听者"处理。这里所说的“信息”实际上就是java.awt.event事件类库里某个类所创建的对象,把它称为“事件的对象”。

线程

线程相关概念
程序

程序是为完成特定任务、用某种语言编写的一组指令的集合。程序简单说就是运行代码。

进程 

进程是指运行中的程序。例如我们使用微信,就启动了一个进程,操作系统就会为该进程分配内存空间。

进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生、存在和消亡过程。

线程

1.线程是由进程创建的,是进程的一个实体。

2.一个进程可以拥有多个线程。 

 单线程和多线程

单线程:同一个时刻,只允许执行一个线程

多线程:同一个时刻,可以执行多个线程,比如:一个QQ进程可以同时打开多个聊天窗口,一个迅雷进程,可以同时下载多个文件。

并发和并行 

并发:同一个时刻,多个任务交替执行,造成一种“貌似同时”的错觉。简单地说,单核cpu实现的多任务就是并发。

并行:同一个时刻,多个任务同时执行多核cpu可以实现并行。

Runtime runtime = Runtime.getRuntime();
        // 获取当前pc的cpu数量
        int cupNums = runtime.availableProcessors();
        System.out.println("当前cpu个数为: "+cupNums);
 创建线程

创建线程的两种方式:

1.继承Thread类,重写run方法。

2.实现Runnable接口,重写run方法。

两种创建方法的区别:

1.从java的设计来看,通过继承Thread或者实现Tunnable接口来创建线程本质上没有区别。从jdk帮助文档可以看到Thread类本身就实现了Runnable接口。

2.实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制

线程注意细节:

1.start底层会创建新的线程,调用run,run就是一个简单的方法调用,不会启动新线程

2.线程优先级的范围,从低到高为:MIN_PRIORITY 1  / NORM_PRIORITY 5  / MAX_PRIORITY 10。

3.interrupt,中断线程,但并没有真正的结束线程。所以一般用于中断正在休眠进程。

4.sleep:线程的静态方法,使当前线程休眠

 线程常用方法

用户线程和守护线程

1.用户线程:也叫工作线程,当线程的任务执行完或通知方式结束。

2.守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束setDaemon(true);

3.常见的守护线程:垃圾回收机制。 

 线程7大状态

 之所以说7种状态,是因为RUNNNALBE中又分为Ready和Running两种状态。

线程生命周期 

 线程同步机制

1.在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性。 

2.也可以这样理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作。

线程同步方法 

Synchronized:

(1)同步代码块:synchronized (对象){// 得到对象的锁,才能操作同步代码

                // 需要被同步代码;}

(2)synchronized还可以放在方法声明中,表示整个方法为同步方法。

public synchronized void m(String name){

          // 需要被同步的代码;}

互斥锁 ​​

静态方法中实现一个同步代码块就要写:synchroized(类名.class){}

互斥锁的注意事项

1.同步方法如果没有static修饰:默认锁为this

2.如果方法使用static修饰,默认锁对象:当前类.class

3.实现的落地步骤:

        需要先分析上锁的代码。

        选择同步代码块或同步方法。

        要求多个线程的锁对象为同一个即可。

线程的死锁 

多个线程占用了对方的锁资源,但不肯相让,导致了死锁。 

释放锁

以下操作会释放锁:

1.当前线程的同步方法、同步代码块执行结束

2.当前线程在同步代码块、同步方法中遇到break、return

3.当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束。

4.当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁。

以下情况不会释放锁:

1.线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,不会释放锁。

2.线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。

IO流

文件 

文件,简单讲就是保存数据的地方

文件流 

文件在程序中是以流的形式来操作的。

流:数据在数据源(文件)和程序 (内存)之间经历的路径。

输入流:数据从数据源(文件)到程序(内存)之间的路径。

输出流:数据从程序(内存)到数据源(文件)的路径。

创建文件的方法
// 三种创建文件的方式

// 第一种方式   
@Test
    public void creat01(){
        String filePath = "d:\\test1.txt";
        File file = new File(filePath);

        try {
            file.createNewFile();
            System.out.println("文件创建成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

// 第二种方式
    public void creat02(){
        File parentFile = new File("d:\\");
        String fileName = "test2.txt";
        File file = new File(parentFile, fileName);

        try {
            file.createNewFile(); // 这里才会在磁盘中创建该文件
            System.out.println("文件创建成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

// 第三种方式
    @Test
public void creat03(){
        String parentPath = "d:\\";
        String filePath = "test3.txt";
        File file = new File(parentPath, filePath);

        try {
            file.createNewFile();
            System.out.println("文件创建成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
获取文件相关信息

分别为:获得文件名字。文件绝对路径。文件父级目录。文件大小(字节)。文件是否存在。是不是一个文件。isDirectory:是不是一个目录。 

目录操作和删除文件

mkdir:创建一级目录。

mkdirs:创建多级目录。

delect:删除空目录或文件。

 IO流原理及流的分类

1.I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。

2.Java程序中,对于数据的输入/输出操作以“流(stream)”,的方式进行。

3.java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据。

流的分类 

Java的IO流共涉及40多个类,实际上非常规则,都是由以上四个抽象基类派生出来的。

 由这四个类派生出来的子类名称都是以其父类名作为子类名后缀

InputStream字节输入流 

 

FileReader和FileWriter 

每次读取或者写入文件之后都要close或者flush文件。

节点流处理流 

 节点流和处理流的区别和联系

 处理流的功能主要体现在以下两方面

对象流

序列化和反序列化 

1.序列化后保存的文件格式,是按照他自己的格式来保存。(.dat文件)

2.基本数据类型int,boolean,char,String他们的包装类等默认实现了Serializable接口,自己定义的类要手动实现Serializable接口。

如果我们希望在反序列化的模块中调用自己定义类的方法,需要向下转型

需要我们将自己定义的类,放到可以引用的位置

 对象流的细节

 标准输入输出流

 

 转换流

 

 打印流

只有输出流,没有输入流。

 PrintStream out = System.out; // 字节打印流

字符打印流

Properties类 

Properties类是专门用于读写配置文件的集合类。

配置文件的格式

键=值 // 必须按照这种格式来,注意:键值对之间不需要有空格,值不需要引号引起来,默认类型是String

Properties类常用方法 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值