1.0_基础篇(下)
8.集合
8.0 集合与数组的区别
- 长度:数组长度固定,集合长度可变
- 内容:数组内容是基本类型或引用类型,集合元素是引用类型
- 元素:数组存储一直类型元素,集合可存多种类型元素
8.1 Collection(单列集合)
- 概述 – 是单列集合的顶层接口
Collection<String> c = new ArrayList<String>();
c.add("hello");
c.add("world");
System.out.println(c); //[hello, world]
- 常用方法
方法名 | 说明 |
---|---|
add(E e) | 集合尾部添加元素 c.add("hello"); |
remove(Object o) | 删除集合中与o相等的元素 c.remove("world"); |
clear() | 清除本集合中所有元素 c.clear(); |
contains(Object o) | 判断集合中是否含o元素 c.contains("hello") |
isEmpty() | 判断是否为空 c.isEmpty() |
size() | 返回集合中元素的个数 c.size() |
addAll(Collection c) | 将 c 集合中所有元素添加到另一个集合 |
iterator | 迭代器,用于遍历集合 |
iterator 使用
ArrayList<String> s = new ArrayList<>(); s.add("111"); s.add("222"); System.out.println(s);//[111, 222] Iterator<String> i = s.iterator(); while (i.hasNext()){ //判断有无下一个元素 System.out.println(i.next()); //获取下一个元素 }
8.2 List
特点:元素 可重复 ,可用索引操作元素
-
LinkedList(增删快,查询慢)【数据结构:链表】
-
ArrayList(查询快,增删慢)【数据结构:数组】
-
特有方法:
- List ----------
方法名 说明 add(int index,Object obj) 在指定位置添加元素 remove(int index) 删除指定位置元素 set(int index,E elment) 修改指定位置元素 get(int index) 获取指定位置元素
- LinkedList ----------(了解)
方法名 说明 addFirst(E e) 将e元素插入列表开头 addLast(E e) 将e元素插入列表末尾 get \ remove 获取和删除元素
-
并发修改异常(迭代器报错)
//前文定义了 Student 类和 s1 等类实例 ArrayList<Student> students = new ArrayList<>(); students.add(s1); Iterator<Student> iterator = students.iterator(); students.add(s2); //会导致iterator.next()触发并发修改异常 System.out.println(iterator.next().getName()); //1.在调用 iterator 方法时,会记录一个预期修改集合次数 Count //2.调用集合的 add 方法时,会为实际修改集合次数 modCount 值 +1 //3.调用 iterator的 next 方法时,会判断预期值与实际值,【若不相等则抛出异常】 //4.使用 get 、 forEach 等方法获取集合元素代替迭代器
注:遍历还有for增强方法,其本质就是在方法内部封装迭代器
for (String s : str) { System.out.println(s); //由于是封装了迭代器,使用也会出现并发异常 }
-
列表迭代器 ListIterator(略:有逆向遍历方法,add 没有并发异常)
8.3 Set(使用迭代器或增强for遍历)
特点:元素 不可重复 ,没有索引
HashSet<String> strs = new HashSet<>(); strs.add("hello"); strs.add("world"); strs.add("world"); System.out.println(strs); //[world, hello]
-
HashSet(对集合的迭代顺序不做保证)【数据结构:哈希表】
哈希值
- 是JDK根据地址(字符串、数字)算出来的 int 类型的数值
- Object.hashCode() 可返回对象的哈希码值(不同对象默认不同)
- 同一个对象多次调用哈希值相同
注:由于对象的不同实例哈希值不同,所以对象所在类中需要重写hashCode方法和equals方法。
-
LinkedHashSet(不重复,保持输入顺序)
-
TreeSet(不重复,默认自然排序)【数据结构:二叉树】
比较器 Comparator
* 在需要排序的对象类中调用Comparable接口,并重写compareTo 方法
//Studen类中,属性:name、team >> 按班级升序排序,同班多人依次打印 @Override public int compareTo(Studen s) { int num = this.team - s.team; //this在前升序,反之降序 if(num==0){ return this.name.compareTo(s.name); //team相同,比较姓名顺序 } return num; }
8.4 泛型
-
8.4.00️⃣ 概念:编译时类型安全检测机制,本质是参数化类型(将类型作为参数)
-
8.4.11️⃣ 格式:
<类型[,类型 ...]>
指定一种类型的格式,类型可看成形参优点:
- 可将部分运行时的才能发现异常提前到编译期
- 可定义不定型类型
-
8.4.22️⃣ 泛型类
格式:修饰符 class 类名 <类型> { … }
public class Demo01<T> { private T str; //不可初始化 public T getStr() { return str; } public void setStr(T str) { this.str = str; } } //泛型类可定义不定型的数据类型,具体类型由传入值决定 //实例 Demo01<String> d1 = new Demo01();
-
8.4.33️⃣ 泛型方法
格式:public void Fn(T str){ … } // 类似于方法重载
-
8.4.44️⃣ 泛型接口
格式:修饰符 interface 接口名<类型>{ … } //例如集合接口 List
-
8.4.55️⃣ 类型通配符
格式:<?> //表示任意类型
通配符上限:<? extends 类型> //该类型 或 其子类型
通配符下限:<? super 类型> //该类型 或 其父类
8.5 Map(双列集合)
- 概述 – 将键映射到值的对象。(一个键映射一个值,键不能重复)
Map<String,String> m = new HashMap<>();
m.put("id001","zhao");
m.put("id002","qiang");
m.put("id002","sun");
System.out.println(m);//{id002=sun, id001=zhao} 出现重复值则覆盖
- 常用方法
方法名 | 说明 |
---|---|
put( K key , V value ) | 添加元素 |
remove(Object key) | 根据键删除元素 |
clear() | 清空集合 |
containsKey(Object key) | 是否存在指定键的元素 |
containsValue(Object value) | 是否存在指定值的元素 |
isEmpty() | 集合是否为空 |
size() | 集合长度 |
Set<Map.Entry<k,y>>entrySet(); | 获取所有键值对对象集合 |
- 获取功能
方法名 | 说明 |
---|---|
get(Object Key) | 根据键获取值 |
Set keySet() | Set<String> kset = m.keySet(); 获取所有键的集合,键是不可重复,使用使用Set |
Collection values() | Collection<String> vset = m.values(); 获取使用值的集合 |
重:使用entrySe遍历集合
Map<String,String> m = new HashMap<>(); m.put("id001","zhao"); m.put("id002","qiang"); m.put("id003","sun"); //使用 entrySet() 方法获取所有键值对对象集合 Set<Map.Entry<String, String>> e = m.entrySet(); for (Map.Entry<String, String> strE : e) { String key = strE.getKey(); String val = strE.getValue(); System.out.println(key+":"+val); } //方法二:先获取所有键的集合,遍历该集合使用get方法找到对应值
8.6 Collections
- 概述:此类是有静态方法组合或返回集合。包含对集合操作的多态算法
方法 | 说明 |
---|---|
sort(List list) | 排序,默认升序 |
reverse(List<?> list) | 反转顺序 |
shuffle(List<?> list) | 随机排序 |
max | min | 最大、最小值 |
9.IO流
IO流:处理设备间数据传输问题(Input/Out)
9.1 File
概述:文件和目录(文件夹)路径名的抽象表示形式
格式:
new File(String pathname)
(根据一个路径得到File对象)例:
File file = new File("E:\\java.txt")
- 常用方法
方法 | 说明 |
---|---|
creatNewFile() | 创建一个新文件(若存在,则不重复创建) |
mkdir() | 创建一个目录(只能创建单层目录) |
mkdirs() | 创建多级目录 |
delete() | 删除文件或者文件夹(只能删除空文件夹) |
isDirectory() | 是否是目录(目录不存在为false) |
isFile() | 是否是文件(文件不存在为fasle) |
exists() | 文件是否存在 |
getName() | 返回此路径表示的文件或目录名称 |
list() | 返回目录中的 文件和目录 的名称字符串数组 |
listFiles() | 返回目录中的 文件和目录 的 File对象数组 |
注意:使用creatNewFile()方法时,需抛出 IO 流异常 IOException
快捷键:选中提示【 Alt+Enter 】>> Add exception…
9.2 字节流
- 9.2.0 概念:
InputStream
与OutputStream
是两个抽象类,是字节流的基类
- IO流父类是按 ⛔️ 数据类型 来分的
- 未加密用字符流,否则用字节流。不确定清空用字节流
- 9.2.1 InputStream
-
编码
new String(byteArr,0,len)
byte数组转字符串 -
FileInputStream( 从文件系统中的文件获取输入字节 )
方法 | 说明 |
---|---|
read() | 读取一个字节的数据 |
⛔️ read(byte[ ] b) | 读取一个字节数组的数据 |
close() | 关闭文件输出流并释放系统资源 |
FileInputStream fileInput = new FileInputStream("demo\\src\\a.txt");
byte[] byteArr = new byte[1024]; //一般为1024或其整数倍
int len; //接收读取文件的长度
while ((len=fileInput.read(byteArr))!=-1){
//将byte数组转为字符串
System.out.print(new String(byteArr,0,len));
}
fileInput.close();
- 9.2.2 OutputStream
-
解码
String.getBytes()
字符串转 byte 数组 -
FileOutputStream( 文件输出流是将数据写入File ,如果第二个参数为true,则为追加)
方法 | 说明 |
---|---|
close() | 关闭文件输出流并释放系统资源 |
write() | 将字节写入文件输出流 |
// 注意:自己处理异常,有利于保证是否发生异常,都能释放资源
FileOutputStream fileOut = null;
try {
fileOut = new FileOutputStream("demo\\src\\java.txt");
byte[] arr = "java".getBytes();// String的方法:将字符串转为byte数组
fileOut.write(arr);//写入文件
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fileOut!=null){ //防止创建对象步骤失败,出现空指针异常
fileOut.close(); //close异常可抛出或自己处理
}
}
// new 关键字调用 FileOutputStream 构造方法
// 1. 创建文件 2.创建字节流输出对象 3.让对象指向文件
-
9.2.3缓冲流
- BufferedInputStream(创建一个缓冲区数组,当从读取字节时填入缓冲区)
- BufferedOutputStream (缓冲输出流,不必为写入每个字节导致底层系统调用)
BufferedInputStream BInput = null; BufferedOutputStream BOutput = null; try { BInput = new BufferedInputStream(new FileInputStream("no\\src\\static\\home_bg.mp4")); BOutput = new BufferedOutputStream(new FileOutputStream("no\\src\\static\\copyd.mp4")); byte[] byteArr = new byte[1024]; //数组大小与读写速度有关 while (BInput.read(byteArr)!=-1){ BOutput.write(byteArr); } } catch (IOException e) { e.printStackTrace(); } finally { try { BInput.close(); BOutput.close(); } catch (IOException e) { e.printStackTrace(); } }
9.3 字符流
-
概念:字符流 = 字节流 + 编码表
-
Reader(输入)
InputStreamReader (FileInputStream对象): 读取字节,并转换为字符
//字节流读取 对比 字符流读取 FileInputStream fInput = new FileInputStream("no\\A.txt"); byte[] bArr = new byte[1024]; //byte int len=0; while ((len=fInput.read(bArr))!=-1){ System.out.print(new String(bArr,0,len)); } //世界你好! fInput.close(); System.out.println("\n\n---- VS ----\n"); InputStreamReader Reader = new InputStreamReader(new FileInputStream("no\\A.txt")); char[] cArr = new char[1024]; //char while (Reader.read(cArr)!=-1){ System.out.print(cArr);//不需要解码 } //世界你好! Reader.close();
-
Writer(输出)
OutputStreamWriter (FileOutputStream对象): 将写入字符编码为字节
-
便捷类(语法糖)
InputStreamReader >> FileReader
OutputStreamWriter >> FileWriter
FileReader fileReader = new FileReader("no\\A.txt"); FileWriter fileWriter = new FileWriter("no\\B.txt"); char[] carr = new char[1024]; while (fileReader.read(carr)!=-1){ fileWriter.write(carr); } fileReader.close(); fileWriter.close();
-
缓冲流
- BufferedReader
- BufferedWriter
9.4 特殊操作流
-
标准输入流
System.in
-
标准输出流
system.out
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int in; while ((in=br.read())!=-1){ System.out.print((char)in); }
-
字节打印流
PrintStream
(只负责输出数据,不负责读数据)PrintStream printStream = new PrintStream("demo1.1\\src\\IO\\b.txt"); printStream.write(97); // a printStream.print(97); // 97 printStream.close();
-
字符打印流
PrintWriter
flush() : 刷新
newLine():换行