目录
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();
        }
    }
}
 
适用场景
适合做文本文件的读写操作










