前言:前面主要涉及到java的基本语法,接下来本篇博客主要记录Java中Collections类、泛型、以及File类、IO流的学习。
目录
OutputStream FileOutputStream(文件字节输出流)
数据结构
数据结构是组织数据的方式,数据结构+算法=程序。
数组是一种基本的数据结构。
基础的数据结构:List、Set、Queue、Map,比较高级的有Tree、Heap。
泛型
英文名:generics
List<String> ret = new ArrayList<>()
什么是泛型?
推荐阅读下面的这篇文章。
还不知道泛型是什么?这一篇深入浅出泛型教学! - 知乎 (zhihu.com)
集合
集合,是没有顺序的。
import java.util.Collection;
分类
单列集合 colleciton
双列集合 Map
Collection的分类
接口 Collection<E>
List<E>
- ArrayList<E>
- LinkedList<E>
Set<E>
- HashSet<E>
- LinkedHashSet<E>
- TreeSet<E>
List系列集合:添加的元素是有序、可重复、有索引
ArrayList、LinkedList:有序、可重复、有索引
Set系列集合:添加的元素是无序、不重复、无索引
- HashSet:无序、不重复、无索引
- LinkedHashSet:有序、不重复、无索引
- TreeSet:按大小默认升序排序、不重复、无索引
collection常用方法
package learn11;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class ListMrjj {
public static void main(String[] args) {
List<String> List = new ArrayList<>();
//添加元素
List.add("mrjj");
List.add("test");
List.add("wy");
// 获取集合的大小
System.out.println(List.size());
//判断集合是否包含某个元素 精确匹配
System.out.println(List.contains("wy"));
System.out.println(List.contains("WY"));
//移除第3个元素
System.out.println(List.remove(2));
System.out.println(List);
//获取特定索引的元素
System.out.println(List.get(0));
//修改指定索引的元素
System.out.println(List.set(0, "Mrjj"));
System.out.println(List);
//集合转为数组
Object[] arr = List.toArray();
System.out.println(Arrays.toString(arr));
//集合中的数据都是字符串
String[] arr2 = List.toArray(new String[List.size()]);
System.out.println(Arrays.toString(arr2));
//清空集合
List.clear();
//判断集合是否为空
System.out.println(List.isEmpty());
//将其中一个集合的数据加入另一个集合中
Collection<String> c1 = new ArrayList<>();
c1.add("test1");
c1.add("test2");
Collection<String> c2 = new ArrayList<>();
c2.add("test_a");
c2.add("test_b");
c1.addAll(c2);
System.out.println(c1);
System.out.println(c2);
}
}
collection遍历方式
迭代器
package learn11;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListLearn {
public static void main(String[] args) {
List<String> List = new ArrayList<>();
List.add("learning");
List.add("wyLearning");
List.add("test");
List.add("wy");
List.add("wangying");
List.add("wyy");
Iterator<String> it = List.iterator();
while (it.hasNext()) {
String name = it.next();
System.out.println(name);
}
}
}
for循环
package learn11;
import java.util.ArrayList;
import java.util.List;
public class ListLearn {
public static void main(String[] args) {
List<String> List = new ArrayList<>();
List.add("learning");
List.add("wyLearning");
List.add("test");
List.add("wy");
List.add("wangying");
List.add("wyy");
for (int i = 0; i < List.size(); i++) {
String s = List.get(i);
System.out.println(s);
}
}
}
Lambda表达式
package learn11;
import java.util.ArrayList;
import java.util.List;
public class ListLearn {
public static void main(String[] args) {
List<String> List = new ArrayList<>();
List.add("learning");
List.add("wyLearning");
List.add("test");
List.add("wy");
List.add("wangying");
List.add("wyy");
//可简写成 List.forEach(System.out::println)
List.forEach(s -> {
System.out.println(s);
});
}
}
List集合
特点
List系列集合:添加的元素是有序、可重复、有索引
ArrayList、LinkedList:有序、可重复、有索引
增删改查
package learn11;
import java.util.ArrayList;
import java.util.List;
public class ListMrjj {
public static void main(String[] args) {
List<String> List = new ArrayList<>();
List.add("mrjj");
List.add("test");
List.add("wy");
System.out.println(List);
System.out.println(List.remove(2));
System.out.println(List);
System.out.println(List.get(0));
System.out.println(List.set(0, "Mrjj"));
System.out.println(List);
}
}
List集合的遍历方式
for循环
package learn11;
import java.util.ArrayList;
import java.util.List;
public class ListLearn {
public static void main(String[] args) {
List<String> List = new ArrayList<>();
List.add("learning");
List.add("test");
List.add("wy");
for (int i = 0; i < List.size(); i++) {
String s = List.get(i);
System.out.println(s);
}
}
}
迭代器
Iterator<String> it = List.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
增强for循环(for)
for (String s : List) {
System.out.println(s);
}
Lambda表达式
List.forEach(s->{
System.out.println(s);
});
数据结构,存储组织数据的方式是不同的。
ArrayList集
底层原理
基于数组实现的
数组的特点
根据索引查询数据是比较快的
删除、添加效率较低
适合场景
根据索引查询数据
不适合场景:
数据量较大时,需要频繁的增删操作
LinkedList集合
底层原理
基于双链表
特点:
查询慢,增删相对较快,首尾元素进行增删改查的速度是极快的
应用场景
设计队列
设计队列(队列,先进先出、后进后出)
实现一个队列
package learn11;
import java.util.LinkedList;
public class ListQueue {
public static void main(String[] args) {
LinkedList<String> queue = new LinkedList<>();
queue.addLast("第1个人");
queue.addLast("第2个人");
queue.addLast("第3个人");
queue.addLast("第4个人");
queue.addLast("第5个人");
queue.addLast("第6个人");
System.out.println(queue);
queue.removeFirst();
queue.removeFirst();
queue.removeFirst();
System.out.println(queue);
}
}
栈
进入栈:压栈、进栈(push)
离开栈:弹栈、出栈(pop)
package learn11;
import java.util.LinkedList;
public class ListQueue {
public static void main(String[] args) {
LinkedList<String> stack = new LinkedList<>();
stack.addFirst("第1颗子弹");
stack.addFirst("第2颗子弹");
stack.addFirst("第3颗子弹");
stack.addFirst("第4颗子弹");
stack.addFirst("第5颗子弹");
stack.addFirst("第6颗子弹");
System.out.println(stack);
System.out.println(stack.removeFirst());
System.out.println(stack.removeFirst());
System.out.println(stack.removeFirst());
System.out.println(stack);
}
}
package learn11;
import java.util.LinkedList;
public class ListQueue {
public static void main(String[] args) {
LinkedList<String> stack = new LinkedList<>();
stack.push("第1颗子弹");
stack.push("第2颗子弹");
stack.push("第3颗子弹");
stack.push("第4颗子弹");
stack.push("第5颗子弹");
stack.push("第6颗子弹");
System.out.println(stack);
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack);
}
}
实际上,push方法就是调用的addFirst方法,pop方法调用的removeFirst方法
Set集合
特点
Set系列集合:添加的元素是无序、不重复、无索引
- HashSet:无序、不重复、无索引
- LinkedHashSet:有序、不重复、无索引
- ++++:按大小默认升序排序、不重复、无索引
HashSet
package learn11;
import java.util.HashSet;
import java.util.Set;
public class SetLearn {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(23);
set.add(67);
set.add(24);
set.add(74);
set.add(33);
set.add(23);
System.out.println(set);
}
}
哈希值
一个int类型的数值,java中每个对象都有一个哈希值
java中的所有对象,都可以调用Object类提供的hashCode方法,返回该对象自己的哈希值
public int hashcode():返回对象的哈希码值
底层原理
基于哈希表实现
哈希表是一种增删改查数据,性能都较好的数据结构
适用场景
不需要存储重复元素,不需要排序,无索引
LinkedHashSet
package learn11;
import java.util.LinkedHashSet;
import java.util.Set;
public class SetLearn {
public static void main(String[] args) {
Set<Integer> set = new LinkedHashSet<>();
set.add(23);
set.add(67);
set.add(24);
set.add(74);
set.add(33);
set.add(23);
System.out.println(set);
}
}
底层原理
基于哈希表实现的
每个元素都额外多了一个双链表的机制记录前后元素的位置
适用场景
需要记住元素的添加顺序,无重复元素存储,增删改查都快
TreeSet
package learn11;
import java.util.Set;
import java.util.TreeSet;
public class SetLearn {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<>();
set.add(23);
set.add(67);
set.add(24);
set.add(74);
set.add(33);
set.add(23);
System.out.println(set);
}
}
底层原理
自定义排序规则
适用场景
需要对元素进行排序,没有重复元素需要存储,增删改查都快
Map集合
键值对集合
键不能重复
Map<K,V>
HashMap<K,V>
LinkedHashMap<K,V>
TreeMap<K,V>
特点
Map系列集合的特点都是由键决定的
HashMap:无序、不重复、无索引
LinkedHashMap:有序、不重复、无索引
TreeMap:按照大小默认升序排序、不重复、无索引
常用方法
package learn11;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapLearn {
public static void main(String[] args) {
Map<String, Double> map = new HashMap<>();
map.put("test1", 170.0);
map.put("test2", 160.0);
map.put("test3", 150.0);
map.put("test4", 140.0);
map.put("test5", 130.0);
System.out.println(map);
System.out.println(map.size());
//根据键获取值
System.out.println(map.get("test1"));
//找不到返回null
System.out.println(map.get("wy"));
//根据键删除元素
map.remove("test5");
System.out.println(map);
//判断是否包含某个键
System.out.println(map.containsKey("test3"));
//判断是否包含某个值
System.out.println(map.containsValue(170.0));
// map.clear();
System.out.println(map);
System.out.println(map.isEmpty());
//获取所有键
Set<String> keys = map.keySet();
System.out.println(keys);
//获取所有值
Collection<Double> values = map.values();
System.out.println(values);
//将其他map集合的数据倒入集合中
Map<String,Integer> map1 = new HashMap<>();
map1.put("python1",10);
map1.put("python2",20);
Map<String,Integer> map2 = new HashMap<>();
map2.put("java1",10);
map2.put("java2",20);
map1.putAll(map2);
System.out.println(map1);
System.out.println(map2);
}
}
遍历方式
for循环
package learn11;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapLearn {
public static void main(String[] args) {
Map<String, Double> map = new HashMap<>();
map.put("test1", 170.0);
map.put("test2", 160.0);
map.put("test3", 150.0);
map.put("test4", 140.0);
map.put("test5", 130.0);
Set<String> keys = map.keySet();
for (String key : keys) {
double value = map.get(key);
System.out.println(key + "==>" + value);
}
}
}
键找值
package learn11;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapLearn {
public static void main(String[] args) {
Map<String, Double> map = new HashMap<>();
map.put("test1", 170.0);
map.put("test2", 160.0);
map.put("test3", 150.0);
map.put("test4", 140.0);
map.put("test5", 130.0);
Set<Map.Entry<String, Double>> entries = map.entrySet();
for (Map.Entry<String, Double> entry : entries) {
System.out.println(entry);
}
map.forEach((k, v) -> {
System.out.println(k + "->" + v);
});
}
}
Lambda表达式
package learn11;
import java.util.HashMap;
import java.util.Map;
public class MapLearn {
public static void main(String[] args) {
Map<String, Double> map = new HashMap<>();
map.put("test1", 170.0);
map.put("test2", 160.0);
map.put("test3", 150.0);
map.put("test4", 140.0);
map.put("test5", 130.0);
map.forEach((k,v) -> {
System.out.println(k+"->"+v);
});
}
}
File
常用方法
只能删除空文件夹
package learn11;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
public class FileLearn {
public static void main(String[] args) throws IOException {
File f1 = new File("D:"+File.separator+"qq\\QQWhatsnew.txt");
System.out.println(f1.getName());
System.out.println(f1.length());
File f2 = new File("D:"+File.separator+"qq");
System.out.println(f2.length());
String[] names = f2.list();
for(String name:names){
System.out.println(name);
}
File[] files = f2.listFiles();
for(File file:files){
System.out.println(file.getAbsolutePath());
}
File f3 = new File("src\\learn");
System.out.println(f3.length());
System.out.println(f3.getName());
System.out.println(f1.isDirectory());
System.out.println(f1.isFile());
long time = f1.lastModified();
SimpleDateFormat sdf = new SimpleDateFormat("yyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(time));
System.out.println(f3.getPath());
System.out.println(f3.getAbsolutePath());
File f4 = new File("D:/testwy.txt");
System.out.println(f4.createNewFile());
File f5 = new File("D:/a/b/c");
System.out.println(f5.mkdirs());
System.out.println(f4.delete());
System.out.println(f5.delete());
System.out.println(f5.delete());
System.out.println(f5.delete());
}
}
递归
典型例子,求阶乘
package learn11;
public class jc {
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n) {
if (n == 1) {
return 1;
} else {
return f(n - 1) * n;
}
}
}
递归应用-搜索文件
package learn11;
import java.io.File;
public class SearchLearn {
public static void main(String[] args) {
searchFile(new File("D:/"), "QQ.exe");
}
public static void searchFile(File dir, String fileName) {
if (dir == null || !dir.exists() || dir.isFile()) {
return;
}
File[] files = dir.listFiles();
if (files != null && files.length > 0) {
for (File f : files) {
if (f.isFile()) {
if (f.getName().contains(fileName)) {
System.out.println("找到了" + f.getAbsolutePath());
}
} else {
searchFile(f, fileName);
}
}
}
}
}
字符集
ASCII
首尾是0,1个字节存储一个字符,总共表示128个字符
GBK
一个中文字符编码成两个字节的形式存储
GBK兼容了ASCII字符集
Unicode字符集
UTF-8
英文字符、数字等只占1个字节,汉字字符占用3个字节
IO流
I是指input,称为输入流,负责把数据读到内存中
O是指output,称为输出流,负责写数据出去
IO流体系
字节流
字节输入流:InputStream FileInputStream
字节输出流:OutputStream FileOutputStream
字符流
字符输入流:Reader FileReader
字符输出流:Writer FileWriter
字节流
FileInputStream(文件字节输入流)
每次读取一个字节
package learn11;
import java.io.FileInputStream;
public class FileInputStreamMrjj {
public static void main(String[] args) throws Exception {
FileInputStream is = new FileInputStream("src\\test");
int b1 = is.read();
System.out.println((char) b1);
int b2 = is.read();
System.out.println((char) b2);
int b3 = is.read();
System.out.println(b3);
int b;
while ((b = is.read()) != -1) {
System.out.println((char) b);
}
is.close();
}
}
每次读取多个字节
package learn11;
import java.io.FileInputStream;
import java.io.InputStream;
public class FileInputStreamTest {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("src\\test");
byte[] buffer = new byte[3];
int len;
while ((len = is.read(buffer)) != -1) {
String rs = new String(buffer, 0, len);
System.out.println(rs);
}
is.close();
}
}
上面读取方法会有中文乱码的问题,用一次性全部读取完字节,可以解决中文乱码的问题
一次性全都读完全部字节
package learn11;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class FileInputStreamAll {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("src\\test");
File f = new File("src\\test");
long size = f.length();
byte[] buffer = new byte[(int) size];
int len = is.read(buffer);
System.out.println(new String(buffer));
System.out.println(size);
System.out.println(len);
}
}
OutputStream FileOutputStream(文件字节输出流)
package learn11;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public class FileOutputStreamTest1 {
public static void main(String[] args) throws Exception {
OutputStream os = new FileOutputStream("src\\test", true);
os.write(97);
os.write('b');
// os.write('泰');
byte[] bytes = "中国,加油".getBytes();
os.write(bytes, 0, 9);
os.write("\r\n".getBytes());
os.close();
}
}
拷贝文件
package learn11;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyPicture {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("C:/Users/HP/Desktop/1.jpg");
OutputStream os = new FileOutputStream("D:/1.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
os.close();
is.close();
}
}
释放资源
try-catch-finally
无论程序是正常执行还是出现异常了,最后一定会执行finally
package learn11;
public class test1 {
public static void main(String[] args) {
try {
System.out.println(10 / 0);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("finally执行了一次");
}
}
}
复制文件时应用try-catch-finally
package learn11;
import java.io.*;
public class CopyPicture {
public static void main(String[] args) throws Exception {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream("src\\test");
os = new FileOutputStream("src\\test1");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(os != null) is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(os != null) os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
try-with-resource
释放资源,自动调用AutoCloseable接口
package learn11;
import java.io.*;
public class CopyPicture {
public static void main(String[] args) throws Exception {
try (
InputStream is = new FileInputStream("src\\test");
OutputStream os = new FileOutputStream("src\\test1");
) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
实用场景
字节流适合做一切文件数据的拷贝(音视频、文本);字节流不适合读取中文内容输出(有乱码)
字符流
每次读取一个字符
package learn11;
import java.io.FileReader;
import java.io.Reader;
public class FileReaderTest1 {
public static void main(String[] args) {
try (Reader fr = new FileReader("src\\test");) {
int c;
while ((c = fr.read()) != -1) {
System.out.print((char) c);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
每次读取多个字符
package learn11;
import java.io.FileReader;
import java.io.Reader;
public class FileReaderTest1 {
public static void main(String[] args) {
try (Reader fr = new FileReader("src\\test");) {
char[] buffer = new char[3];
int len;
while ((len = fr.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, len));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
FileWriter(文件字符输出流)
需要注意:关闭流包含了刷新流
字符输出数据后,必须刷新流,或者关闭流。
package learn11;
import java.io.FileWriter;
import java.io.Writer;
public class FileWriterTest1 {
public static void main(String[] args) {
try (Writer fw = new FileWriter("src\\test",true);) {
fw.write('a');
fw.write(99);
fw.write('测');
fw.write("中国,加油!", 0, 3);
fw.write("\r\n");
char[] buffer = {'测', '试', 'a', 'b', 'c'};
fw.write(buffer);
fw.write(buffer, 0, 2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
适用场景
适合做文本文件的读写操作