Java学习-------第四周知识点总结

这篇博客主要介绍了Java集合框架,包括List、Set和Map的定义、特点和常用子类,如ArrayList、LinkedList和HashSet。此外,还讲解了File类、IO流的基本概念,包括字节流和字符流,以及对象序列化流。最后,涉及了进程与线程、互斥锁以及网络通讯的基础知识。
摘要由CSDN通过智能技术生成

集合框架

定义

Java中的一种工具类,用于存储任意数量的具有共同属性的对象;

Java集合主要分为三种:Set(集) List(链表) Map(映射)

三种区别:

  • List可以根据索引直接操作元素,故List能保证它的插入顺序排序;而Set不能通过索引获取元素,故它是无序的,存储和取出顺序不一致;元素可以重复;
  • List的元素可以重复,而Set的元素唯一,不可重复,重复元素会覆盖掉;
  • List,Set都是继承自Collection接口,Map则不是
  • Set和List对比:
    Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
    List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
  • Map 没有继承 Collection 接口,Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value

集合的作用:用于数据有组织的存储,同时简单快速的搜索查找到所需元素,并作出删除或修改;

​ 有的集合接口提供了有序的方法来获取元素,有的通过关键字key去查找唯一对象;

集合与数组的区别:长度上,集合可以改变自身的长度大小,而数组不能;元素类别上,数组可以是任意类型包括基本数据类型在内的任意一种类型;而集合只能存储引用类型;

基本方法

add() 在集合末尾添加元素e
remove()删除某个元素并返回true
clear()清空集合内的所有元素;
contains() 判断集合内是否存在某个元素
isEmpty() 判断元素是否为空
size() 返回集合元素个数
addAll() 将一个集合所有元素添加到另一个集合
toArray() 返回一个数组,包含集合内的所有元素
iterator()迭代器,用于遍历所有元素

集合常用的子类

List集合

LinkedList,ArrayList,Vector
三者区别:

  • LinkedList的底层数据结构是链表,查询慢,增删快,效率高,但线程不安全;

    可以对他的某个元素的顶部或末尾快速操作,如addFirst()、addLast()等独有方法;

  • ArrayList的底层数据结构是数组,查询快,增删慢,效率高,但线程不安全;

  • Vector的底层数据结构是数组,查询快,增删慢,效率低,但线程安全;

ArrayList与LinkedList的区别和适用场景
Arraylist:
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。

LinkedList:
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
适用场景分析
当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。

扩展的功能方法:

add(index,object)在该下标下添加元素,若已经有元素存在,则已有元素向后移动;

remove(index) 删除某个下标的元素,并返回改元素;

set(index,object);修改某个下标的元素,并返回修改前的元素;

indexof(object);返回该元素在集合中第一次出现的下标位置;

get(index);获取该下标位置的元素;

subList(fromIndex,toIndex);截取包括起始坐标,但不包括结束坐标的在内的所有集合元素;

Set集合

HashSet

底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素;通过重写hashCode()和equals()方法保证元素的唯一性;

LinkedHashSet:

底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。

TreeSet:

底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。

Set具有与Collection完全一样的接口,因此没有任何额外的功能;Set 存入的每个元素都必须是唯一的,因为Set不保存重复元素。

List与Set的使用场景:

在这里插入图片描述

Map集合

Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。

主要方法

containsKey(Object key);查询Map中是否存在包含指定key,存在则返回true;

containsValue(Object Value)查询Map中是否存在包含指定Value,存在则返回true;

entrySet();返回一个Map的内部类Entry,Entry中包含Map中包含的键值Key所组成的Set集合;

get(Object key);返回key值对应的value,若无则为null;

put(Object key,Object value);添加元素;

values();返回一个Collection包含所有value值;

种类

HashMap、Hashtable、TreeMap

区别:

  • Hashtable是同步的,线程安全;HashMap是异步的,线程并不安全
  • HashMap可以有多个value值为null,但只允许一个key值为null;而Hashtable不允许放入任何空值;
  • HashMap性能最好,HashTable性能最差;
  • TreeMap的key值以TreeSet形式存储;

File类

创建对象:File file = new File("path")//path文件目录
判定文件是否存在:file.exists();
file.createNewFile();创建文件
file.mkdir();创建文件夹(只能创建一级目录)
file.mkdirs();创建多级目录
file.getName();获取文件名
file.getAbsolutePath();获取绝对路径(完整的路径)
file.getPath();获得创建文件时传入的路径
file.isFile();判断是否为文件
file.isDirectory();判定是否为文件夹
file.length();获取文件大小(字节数)
file.getParent();获取父目录
file.lastModified();获取最后一次修改时间
file[] file.listFiles();取出文件夹中的所有文件
file.delete();删除文件

IO流

IO流

流,顾名思义,就是流动,在Java中即为数据的流动,而相对的,IO则为输入(Input)与输出(Output),在Java中,从程序(内存)到外打的数据则为输出,到内则为输入;

在现实中,流动的数据可以是文件、网络、内存等等,而在现实中水的流动是无序的,为了让水有序,则需要添加管道,因此数据的传输也同样需要管道,在Java中的实现则为流,IO流;

根据流的分类,可分为三种

  • 根据处理的数据单位(大小)不同,可分为:字符流,字节流;
  • 根据流动方向不同,可分为输入流,输出流;
  • 根据功能不同,可分为节点流,处理流;

1、流的分类
节点流:FileInputStream和FileOutputStream
处理流:BufferedInputStream和BufferedOutputStream
DataInputStream和DataOutputStream
输出流中的字节流为:InputStream,字符流为Reader;
输入流中的字节流为:OutputStream,字符流为Writer;
字节流:
FileInputStream 具体实现了在文件上读取数据
FileOutputStream 实现了想文件中写出byte数据的方法
DataOutputStream/DataInputStream
字节缓冲流:BufferedInputStream和BufferedOutputStream;
字符流:
BufferedReader(一次读一行)
BufferedWriter/PrinterWriter(一次写一行)

节点流:

水的源头,即数据的源头,从源头进出的流成为节点流,该流一般直接操作文件、网络等等流,

例如:FileInputStream和FileOutputStream;

  • FileInputStream 具体实现了在文件上读取数据
  • FileOutputStream 实现了想文件中写出byte数据的方法

处理流:

对已经存在的流进行进一步的包装处理,

如BufferedInputStream和BufferedOutputStream

以及DataInputStream和DataOutputStream

字符流:

BufferedReader(一次读一行)

BufferedWriter/PrinterWriter(一次写一行)

对象序列化流

对象序列化流:

将Object转换为byte序列,反之叫对象的反序列化
例如将对象保存到文件中,或者在网上传输,都需要进行对象序列化操作

序列化流(ObjectOutputStream) ---- writeObject
反序列化流(ObjectInputStream)---- readObject

序列化接口(Serializable):对象必须实现序列化接口,才能进行序列化,否则将出现异常。

transient:该元素不会进行默认的序列化

进程与线程

线程Thread:
Thread.sleep(1000);1000为毫秒,
Thread.start();
Thread.currentThread().getname();得到当前线程;
Thread.setName();修改当前线程的名字(启动线程前修改)
new Thread(Runnable,name);新建线程名为name且运行转态为Runnable的线程

创建线程的方法:
1、继承Thread类,重写Thread.run()方法;(启动线程后默认调用)父类引用子类
2、继承接口的方式:Runnable,重写run方法;
3、匿名内部类:

5大线程状态:

在这里插入图片描述

新状态:还未调用start方法的已经创建的线程
可运行状态:有资格被程序调动但程序并未执行,可以从运行、阻塞/等待/睡眠状态回到可运行状态;
运行状态:执行程序;可以进入阻塞状态或睡眠状态;
等待/阻塞/睡眠状态:线程是是活的,但某种条件下并未执行,仅能返回到可运行状态
死亡状:run()方法执行完毕后,即使线程可能是活的,但已经被认为死亡状态,不能在重新调用start状态,否则会发生异常;

互斥锁与锁

多个线程运作中,容易出现多个线程访问同一个数据或者线程,这种情况容易出现数据的损坏;

为了避免多线程操作单一对象,提出来锁的设计,在Java中每个的对象都有一个内置锁;

而用非静态的synchronized同步方法,将代码块圈住,则获得的第一个对象的锁,并只能运行该锁进入;因而避免了多个线程的进入;

语法结构:synchronized(对象){代码块;}

关于锁和同步,有一下几个要点:

  1. 只能同步方法,而不能同步变量和类;
  2. 每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步?
  3. 如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。
  4. 线程睡眠时,它所持的任何锁都不会释放。
  5. 同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。
  6. 在使用同步代码块时候,应该指定在哪个对象上同步,也就是说要获取哪个对象的锁。
  7. 线程的安全性:当一个类已经很好的同步以保护它的数据时,这个类就称为“线程安全的”。

除此之外,也容易出现死锁的状态,故提出了互斥锁

互斥锁有三个方法,wait()以及notify(),notifyAll();

关于wait()以及notify(),notifyAll();

wait()和notify()

程序执行wait()时,线程进入等待状态
程序执行notify()时,唤醒处于wait状态的线程

wait()和notify()方法定义在Object类中,所以任何对象都可以调用,但是必须在synchronized同步方法或代码块才能调用,否则会产生异常。
要尽量避免死锁发生。如果程序中两条线程都进入wait()状态,那么彼此无法唤醒对方,就进入到了死锁。
如果进入wait状态的线程不止一条,调用notify()只能唤醒其中的一条,而且无法指定是哪一条。如果要全部唤醒,则可调用notifyAll()。

网络通讯连接

TCP/IP协议的使用

步骤:

//1. 服务端建立服务端,自定义自己服务端的端口号:
ServerSocket server =new ServerSocket(9999);
//2. 客户端新建一个用于连接服务端的管道,包装服务器IP以及端口;
Socket socket  = new Socket("xxxx",9999)
//3. 服务端等待连接,而连接成功则会生成一个管道,用于数据传输
Socket socket  = server.accept;
//此socket与IO流相结合,进行网络之间的数据传输

UDP的使用

步骤:

//发送方:
//1. 发送方新建数据包,用于打包接收方的IP地址以及端口号,包括要发送的数据内容
DatagramPacket dp = new DatagramPacket(text.getBytes(), 0, text.getBytes().length,socketList.get(i).getInetAddress(),socketList.get(i).getPort());//对应参数为文本字节,起始位置,文本长度,接收方IP,接收方端口;

//2. 发送方新建用于连接网络层的管道
DatagramSocket ds = new DatagramSocket();

//3.将数据包放入发送管道,发送数据包至网络层
ds.send(dp);

//接收方:
//4.接收方新建用于连接网络层的管道,此时需要添加自身本地端口
DatagramSocket ds = new DatagramSocket(new Socket().getLocalPort());

//5. 新建用于接收数据的数据包
dp = new DatagramPacket(new byte[1024], 1024);

//6. 从管道中接收与端口号相同的数据包,并放入自定义的数据包
ds.receive(dp);

//过程结束
//可能有误,或者部分方法的参数解释



部分内容取至某些文章,如有问题,请与我联系,也同时感谢这些博主的知识交流!!!

https://blog.csdn.net/feiyanaffection/article/details/81394745

https://www.cnblogs.com/yichunguo/p/11775270.html#22-字节输出流(outputstream)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值