day11-StreamFile

news2024/11/24 15:01:50

1.Stream流

1.1 体验Stream流

需求:按照下面的要求完成集合的创建和遍历
创建一个集合,存储多个字符串元素
把集合中所有以"杨"开头的元素存储到一个新的集合
把"杨"开头的集合中的长度为3的元素存储到一个新的集合
遍历上一步得到的集合

public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        ArrayList<String> newList = new ArrayList<>();
        ArrayList<String> newList2 = new ArrayList<>();
        list.add("杨金辉");
        list.add("杨大");
        list.add("杨老二");
        list.add("小杨哥");
        list.add("赵信");
        for (String s : list) {
            if (s.startsWith("杨")){
                newList.add(s);
            }
        }
        System.out.println(newList);

        for (String s : newList) {
            if (s.length()==3){
                newList2.add(s);
            }
        }
        System.out.println(newList2);
    }

1.2 为什么要用Stream流

简化集合操作的

1.3 Stream流思想

在这里插入图片描述

在这里插入图片描述

1.4 Stream流的三类方法

我们可以把stream流看做是一条流水线。

Stream流的使用,它有这样的一些操作,首先来说是生成流,你要使用Stream流,你得有一个Stream流

forEach指的是为每一个元素执行操作

获取Stream流
创建一条流水线,并把数据放到流水线上准备进行操作

中间方法
流水线上的操作。
一次操作完毕之后,还可以继续进行其他操作

终结方法
一个Stream流只能有一个终结方法
是流水线上的最后一个操作

1.5 Stream流的获取方法

单列集合
可以使用Collection接口中的默认方法stream()生成流
default Stream stream()
双列集合
间接的生成流
可以先通过keySet或者entrySet获取一个Set集合,再获取Stream流
数组
数组:Arrays.stream(数组) / Stream.of(数组);

同种数据类型的多个数据
1,2,3,4,5….
“aaa”,“bbb”,“ccc”….
使用Stream.of(T…values)生成流

代码:

ArrayList<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();

Map<String,Integer> map = new HashMap<>();
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Stream<Map.Entry<String, Integer>> stream1 = entries.stream();

Integer[]arr={1,2,3,4,5};
Stream<Integer> stream2 = Arrays.stream(arr);
Stream<Integer> arr1 = Stream.of(arr);

Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
Stream<String> aaa = Stream.of("aaa", "bbb", "ccc");

1.6 Stream流的常见中间操作方法

Stream filter​(Predicate predicate):用于对流中的数据进行过滤

Predicate接口中的方法
boolean test(T t):对给定的参数进行判断,返回一个布尔值 

Stream limit(long maxSize):截取指定参数个数的数据 取集合中的前几个

Stream skip(long n):跳过指定参数个数的数据 跳过集合中的前几个

static Stream concat(Stream a, Stream b):合并a和b两个流为一个流

Stream distinct():去除流中重复的元素。依赖(hashCode和equals方法)

map(Function(<? Super T>,<? Extends R> mapper)):数据类型转化

1.7 Stream流的常见终结操作方法

void forEach​(Consumer action):对此流的每个元素执行操作
Consumer接口中的方法 void accept​(T t):对给定的参数执行此操作
long count​():返回此流中的元素数

我们可以理解stream流的操作为:未加工的产品 -------加工--------加工后的产品

 public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("马大哈");
        list.add("马守信");
        list.add("赵强");
        list.add("马强");
        list.add("马飞");
        list.add("张三民");
        list.add("张三民");
     
		// 未加工的产品 -------加工--------加工后的产品
        //统计加工之后的产品
        list.stream().forEach(s -> System.out.println(s));

        //统计加工之后的产品个数
        long count1 = list.stream().count();
        System.out.println("加工后的产品个数为:" + count1);

        //找所有姓马的
list.stream().filter(s -> s.startsWith("马")).forEach(s -> System.out.println(s));

        //统计名字为3个字的个数
        long count = list.stream().filter(s -> s.length() == 3).count();
        System.out.println(count);
        
        //取集合中前两个姓马的
list.stream().filter(s -> s.startsWith("马")).limit(2).forEach(System.out::println);

        //跳过集合中前两个姓马的
list.stream().filter(s -> s.startsWith("马")).skip(2).forEach(System.out::println);
     
    	//map加工方法: 第一个参数原材料  -> 第二个参数是加工后的结果。
      	//对集合中每个元素都加入前缀
        list.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {
                return "高合的" + s;
            }
        }).forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
     	//简化
        list.stream().map(s -> "高合的" + s).forEach(s -> System.out.println(s));

        //需求 把所有的名称都加到一个学生类中
        list.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {
                return new Student(s);
            }
        }).forEach(new Consumer<Student>() {
            @Override
            public void accept(Student student) {
                System.out.println(student);
            }
        });
     	//简化后
        list.stream().map(s -> new Student(s)).forEach(s -> System.out.println(s));
//      list.stream().map(Student::new).forEach(System.out::println); // 构造器引用  方法引用
        // 合并流。
        Stream<String> s1 = list.stream().filter(s -> s.startsWith("张"));
        Stream<String> s2 = Stream.of("java1", "java2");
      // public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
        Stream<String> s3 = Stream.concat(s1 , s2);
        s3.distinct().forEach(s -> System.out.println(s));
    }

Student

public class Student {
    private String name;

   有参/无参/get/set/tostring
}

补充

这里的System.out::println确实是实现Consumer<T>接口的匿名函数,而且这里用的是Lambda表达式中的方法引用语法。方法引用实际上是将一个Lambda表达式的实现指向一个已经实现了的方法,
    语法为——方法的隶属者::方法名。
对于System.out::println来说,System.out就是方法的隶属者,println就是已实现的方法。我们依然找到它的源码。

1.8 Stream流的收集操作

使用Stream流的方式操作完毕之后,我想把流中的数据起来,该怎么办呢?

Stream流的收集方法
R collect​(Collector collector)

工具类Collectors提供了具体的收集方式
public static Collector toList​():把元素收集到List集合中
public static Collector toSet​():把元素收集到Set集合中
public static Collector toMap​(Function keyMapper,Function valueMapper):把元素收集到Map集合中

代码展示:

List<String> list = new ArrayList<>();
list.add("马大哈");
list.add("马守信");
list.add("马守信");
list.add("赵强");
list.add("马强");
list.add("马飞");
list.add("张三民");
list.add("张三民");

//        List<String> collect = list.stream().filter(new Predicate<String>() {
//            @Override
//            public boolean test(String s) {
//                return s.length() == 3;
//            }
//        }).collect(Collectors.toList());
        List<String> collect = list.stream().filter(s -> s.length() == 3).collect(Collectors.toList());
        System.out.println(collect);

//        Set<String> collect1 = list.stream().filter(new Predicate<String>() {
//            @Override
//            public boolean test(String s) {
//                return s.length() == 3;
//            }
//        }).collect(Collectors.toSet());
        Set<String> collect1 = list.stream().filter(s -> s.length() == 3).collect(Collectors.toSet());
        System.out.println(collect1);


//        Map<Student, Integer> collect2 = list.stream().filter(new Predicate<String>() {
//            @Override
//            public boolean test(String s) {
//                return s.length() == 3;
//            }
//        }).collect(Collectors.toMap(new Function<String, Student>() {
//            @Override
//            public Student apply(String s) {
//                return new Student(s);
//            }
//        }, new Function<String, Integer>() {
//            @Override
//            public Integer apply(String s) {
//                return 1;
//            }
//        }));
//        Map<Student, Integer> collect2 = list.stream().filter(s -> s.length() == 3).collect(Collectors.toMap(s -> new Student(s), s -> 1));
        Map<Student, Integer> collect2 = list.stream().filter(s -> s.length() == 3).collect(Collectors.toMap(Student::new, s -> 1));
        System.out.println(collect2);

        //转为数组类型
        Stream<String> stream = list.stream().filter(s -> s.startsWith("马"));
        String[] strings = stream.toArray(String[]::new);// 可以不管,拓展一下思维!!
        System.out.println(Arrays.toString(strings));

1.9 总结

1.Stream流的作用
结合了Lambda表达式,简化集合、数组的操作
2.stream的使用步骤
a.获取Stream流对象
b.使用中间方法处理数据
c. 使用终结方法处理数据

3.如何获取Stream流对象
a.单列集合: Collection中的默认方法stream
b.双列集合:不能直接获取
c. 数组: Arrays工具类型中的静态方法stream
d.一堆零散的数据: stream接口中的静态方法of
4.常见方法
中间方法:filter, limit, skip, distinct, concat, map
终结方法:forEach, count, collect

1.10.1 Stream流的练习1

1.10.1 过滤元素并遍历集合

需求:过滤元素并遍历集合

定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
将集合中的奇数删除,只保留偶数。
遍历得到的集合输出2,4,6,8,10

//1.定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
list.add(8);
list.add(9);
list.add(10);
//将集合中的奇数删除,只保留偶数。遍历得到的集合输出2,4,6,8,10
list.stream().filter(integer -> integer % 2 == 0).forEach(System.out::println);

结论:在Stream流中无法直接修改集合,数组等数据源中的数据。

1.10.2 Stream流的练习2

练习:
创建一个ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年龄
“zhangsan,23”
“lisi,24”
“ wangwu,25”
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值

public static Collector toMap​(Function keyMapper , Function valueMapper):把元素收集到Map集合中

 public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("zhangsan,23");
        list.add("lisi,24");
        list.add("wangwu,25");

//        Map<String, Integer> collect = list.stream().filter(s -> {
//            String[] split = s.split(",");
//            return Integer.parseInt(split[1]) >= 24;
//        }).collect(Collectors.toMap(new Function<String, String>() {
//            @Override
//            public String apply(String s) {
//                return s.split(",")[0];
//            }
//        }, new Function<String, Integer>() {
//            @Override
//            public Integer apply(String s) {
//                return Integer.parseInt(s.split(",")[1]);
//            }
//        }));


        Map<String, Integer> collect = list.stream().filter(s -> Integer.parseInt(s.split(",")[1]) >= 24)
                .collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
        System.out.println(collect);
    }

1.10.3 Stream流的练习3

现在有两个ArrayList集合,分别存储6名男演员和6名女演员,要求完成如下的操作
男演员只要名字为3个字的前两人
女演员只要姓杨的,并且不要第一个姓杨的
把过滤后的男演员姓名和女演员姓名合并到一起
把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
演员类Actor,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法

public static void main(String[] args) {
        ArrayList<Actor> man = new ArrayList<>();
        man.add(new Actor("杨树林"));
        man.add(new Actor("文松"));
        man.add(new Actor("宋小宝"));
        man.add(new Actor("赵本山"));
        man.add(new Actor("小沈阳"));
        man.add(new Actor("王金龙"));
        ArrayList<Actor> woman = new ArrayList<>();
        woman.add(new Actor("欧阳娜娜"));
        woman.add(new Actor("热依扎"));
        woman.add(new Actor("古力娜扎"));
        woman.add(new Actor("杨颖"));
        woman.add(new Actor("杨千嬅"));
        woman.add(new Actor("杨丽"));

        //男演员只要名字为3个字的前两人
        Stream<Actor> manStream = man.stream().filter(actor -> actor.getName().length() == 3).limit(2);
        //女演员只要姓杨的,并且不要第一个姓杨的
        Stream<Actor> womanStream = woman.stream().filter(actor -> actor.getName().startsWith("杨")).skip(1);
        //把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
        Stream.concat(manStream,womanStream).forEach(System.out::println);
    }

2.File

思考:以前是如何存储数据的?

int a = 10;
int [] arr = {1,2,3,4,5};
ArrayList<String> list = new ArrayList<>();

弊端是什么?

不能永久化存储,只要代码运行结束,所有数据都会丢失。

思考:计算机中,有没有一个硬件可以永久化存储?

在这里插入图片描述

我们可以对硬盘进行哪些操作?

在这里插入图片描述

对文件进行读写的前提条件?

1.我们得知道这个文件在哪

IO就可以对硬盘中的文件进行读写File表示要读写的文件在哪,也可以对文件进行创建,删除等操作

总结

1.IO流是什么?
a.可以将数据从本地文件中读取出来

b.可以将数据从内存保存到本地文件

2.File类是什么?

a.在读写数据时告诉虚拟机要操作的(文件/文件夹)在哪

b.对(文件/文件夹)本身进行操作。包括创建,删除等。

2.1 File类概述和构造方法

File:它是文件和目录路径名的抽象表示

文件和目录可以通过File封装成对象

File封装的对象仅仅是一个路径名。它可以是存在的,也可以是不存在的。

方法名说明
File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File(String parent, String child)从父路径名字符串和子路径名字符串创建新的 File实例
File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例
路径写法: / \\ File.separator

代码:

File file1 = new File("E:/file/ikun2.jpeg");
File file2 = new File("E:\\file\\ikun2.jpeg");
File file3 = new File("E:" + File.separator + "file" + File.separator + "ikun2.jpeg");
System.out.println(file1.length());
System.out.println(file2.length());
System.out.println(file3.length());
System.out.println("------------");
File file4 = new File("E:/file/","ikun2.jpeg");
System.out.println(file4.length());
File file5 = new File(new File("E:/file/"),"ikun2.jpeg");
System.out.println(file5.length());

2.2 绝对路径和相对路径

绝对路径:从盘符开始

File file1 = new File(“D:\\itgaohe\\a.txt”); 

相对路径:相对当前项目下的路径

1.从项目中找到目标文件右键 copy path—> path from content root

2.如果是分模块创建 则加上模块名!!!!

File file2 = new File(“a.txt”);
//如果是分模块创建 则加上模块名!!!!
File file3 = new File(“模块名\\a.txt”); 

在这里插入图片描述

2.3 File类创建功能

方法名说明
public boolean createNewFile()创建一个新的空的文件
public boolean mkdir()创建一个单级文件夹
public boolean mkdirs()创建一个多级文件夹
		  File f3 = new File("E:\\abc\\aa\\aaa");
//        System.out.println(f3.createNewFile());
//        System.out.println(f3.mkdir());
//        System.out.println(f3.mkdirs());

2.4 File类删除功能

方法名说明
public boolean delete()删除由此抽象路径名表示的文件或目录

删除目录时的注意事项:
delete方法直接删除不走回收站。
如果删除的是一个文件,直接删除。
如果删除的是一个文件夹,需要先删除文件夹中的内容,最后才能删除文件夹。

2.5 File类判断和获取功能

方法名说明
public boolean isDirectory()测试此抽象路径名表示的File是否为目录
public boolean isFile()测试此抽象路径名表示的File是否为文件
public boolean exists()测试此抽象路径名表示的File是否存在
public String getAbsolutePath()返回此抽象路径名的绝对路径名字符串
public String getPath()将此抽象路径名转换为路径名字符串
public String getName()返回由此抽象路径名表示的文件或目录的名称
// 1.绝对路径创建一个文件对象
File f1 = new File("D:/resources/xueshan.jpeg");
// a.获取它的绝对路径。
System.out.println(f1.getAbsolutePath());
// b.获取文件定义的时候使用的路径。
System.out.println(f1.getPath());
// c.获取文件的名称:带后缀。
System.out.println(f1.getName());
// d.获取文件的大小:字节个数。
System.out.println(f1.length()); // 字节大小
// e.获取文件的最后修改时间
long time = f1.lastModified();
System.out.println("最后修改时间:" + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(time));
// f、判断文件是文件还是文件夹
System.out.println(f1.isFile()); // true
System.out.println(f1.isDirectory()); // false

//相对路径创建一个 
//File f3 = new File("src/com/itgaohe/123.txt");

2.6 File类高级获取功能

方法名说明
public File[] listFiles()获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)

listFiles方法注意事项:
当调用者不存在时,返回null
当调用者是一个文件时,返回null
当调用者是一个空文件夹时,返回一个长度为0的数组
当调用者是一个有内容的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回
当调用者是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏内容
当调用者是一个需要权限才能进入的文件夹时,返回null

File file = new File("E:\\abc");
        File[] files = file.listFiles();
        //获取一级文件目录
        for (File file1 : files) {
            System.out.println(file1);
        }

2.7 练习:

练习一:在当前模块下的images文件夹中创建一个a.txt文件
练习二:删除一个文件
练习三:在当前模块下的images文件夹中创建一个aaa文件夹
练习四:删除一个文件夹

File file = new File("E:\\IdeaProject\\GHA2340\\java_makeup01\\file01\\image\\a.txt");
System.out.println(file.length());
System.out.println(file.delete());

File file1 = new File("E:\\IdeaProject\\GHA2340\\java_makeup01\\file01\\image\\aaa");
System.out.println(file1.delete());

2.8 案例:File的练习

练习1:在当前模块下的aaa文件中创建一个a.txt文件

File file = new File("E:\\IdeaProject\\GHA2340\\java_makeup01\\file01\\image\\aaa\\a.txt");
file.createNewFile();

练习2:删除一个多级文件夹

public static void main(String[] args) {
    deleteDir(new File("E:\\abc"));
}

public static void deleteDir(File dir) {
    //1.判断dir是否存在 并且还是个文件夹
    if (dir.isDirectory() && dir != null && dir.exists()) {
        //dir != null 说明有内容  不能直接删除!
        //2.提取一级文件对象
        File[] files = dir.listFiles();
        //3.判断一级文件对象是否存在 如果存在则遍历全部的一级文件对象并且删除
        if (files != null && files.length > 0) {
            //文件夹中有内容
            //4.遍历 判断file是文件还是文件夹
            for (File file : files) {
                if (file.isFile()) {
                    //5.如果是文件 则直接删除
                    file.delete();
                } else {
                    //6.不是文件 还是文件夹
                    deleteDir(file);
                }
            }
        }
        //删除
        dir.delete();
    }
}

练习3:统计一个文件夹中每种文件的个数并且打印
打印格式如下:
txt: 3个
doc:4个
jpg: 6个

public static void main(String[] args) {
    int txt = 0;
    int doc = 0;
    int jpg = 0;
    //1.定位文件夹
    File file = new File("E:/abc");
    String[] list = file.list();
    for (String s : list) {
        System.out.println(s);
        if (s.endsWith("txt")){
            txt++;
        }else if (s.endsWith("doc")){
            doc++;
        }else if (s.endsWith("jpg")){
            jpg++;
        }
    }
    System.out.println("txt:" + txt + "个");
    System.out.println("doc:" + doc + "个");
    System.out.println("jpg:" + jpg + "个");
}

习3:统计一个文件夹中每种文件的个数并且打印
打印格式如下:
txt: 3个
doc:4个
jpg: 6个

public static void main(String[] args) {
    int txt = 0;
    int doc = 0;
    int jpg = 0;
    //1.定位文件夹
    File file = new File("E:/abc");
    String[] list = file.list();
    for (String s : list) {
        System.out.println(s);
        if (s.endsWith("txt")){
            txt++;
        }else if (s.endsWith("doc")){
            doc++;
        }else if (s.endsWith("jpg")){
            jpg++;
        }
    }
    System.out.println("txt:" + txt + "个");
    System.out.println("doc:" + doc + "个");
    System.out.println("jpg:" + jpg + "个");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1667168.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】图的应用---最小生成树(Prim,Kruskal)、最短路径(BFS,Dijkstra,Floyd)、拓扑排序、关键路径、有向无环图表达式

文章目录 5.图的应用5.1 最小生成树5.1.1 Prim算法5.1.2 Kruskal算法5.1.3 最小生成树代码A.邻接矩阵B.邻接表 5.2 最短路径5.2.1 BFS5.2.2 Dijkstra5.2.3 Floyd5.2.4 三种算法的比较 5.3 有向无环图描述表达式5.4 拓扑排序5.5 关键路径 5.图的应用 5.1 最小生成树 定义 对一个…

uniapp获取当前位置及检测授权状态——支持App、微信小程序

uniapp获取当前位置检测及定位权限——支持App、微信小程序 首先&#xff0c;祝天下母亲&#xff0c;节日快乐~ 文章目录 uniapp获取当前位置检测及定位权限——支持App、微信小程序效果图新增 兼容小程序方法manifest Tips&#xff1a; 上一篇介绍 App端 uniapp获取当前位置及…

分布式与一致性协议之PBFT算法(二)

PBFT算法 如何替换作恶的主节点 虽然PBFT算法可以防止备份节点作恶&#xff0c;因为这个算法是由主节点和备份节点组成的&#xff0c;但是&#xff0c;如果主节点作恶(比如主机点接收到了客户端的请求&#xff0c;但就是默不作声&#xff0c;不执行三阶段协议)&#xff0c;那…

C脚本实现Wincc弹窗重复调用

文章目录 前言一、步骤及解析二、运行画面演示三、总结 前言 在常见的Wincc上位机画面中&#xff0c;点击按钮或控件弹出弹窗&#xff0c;由于不同的弹窗内容不同&#xff0c;变量前缀不同&#xff0c;通常情况下一个弹窗就需要调用一个画面窗口&#xff0c;但画面窗口过多会导…

Redis经典问题:数据不一致

大家好,我是小米,今天我想和大家聊一聊Redis的一个经典问题——数据不一致。在使用Redis的过程中,你是否曾遇到过这样的问题?缓存和数据库中的数据不一致,可能导致应用程序的功能异常。下面,我将详细介绍数据不一致的原因,以及一些有效的解决方案。 什么是数据不一致 …

【muzzik 分享】Cocos 物理帧同步

# 前言 之前没研究帧同步&#xff0c;这是我前端时间没上班时边玩边搞做的 Demo 研究成果&#xff0c;总共时间一周&#xff08;实际2-3天&#xff09;&#xff0c;发布的目的也很简单&#xff0c;打破技术垄断&#xff0c;才能诞生更高端的技术成果。而且就算我没发这篇帖子&…

The 2023 ICPC Asia Hefei Regional Contest

目录 B. Queue Sorting 应该还会再补几题 B. Queue Sorting 题解&#xff1a; Dilworth定理: 【偏序关系与偏序集、Hasse图、极大元、极小元、全序关系、最大元、良序集/三小时讲不完离散数学之集合论/考研复试/期末复习考前冲刺/近世代数/抽象代数】https://www.bilibili.c…

【ARM 嵌入式 C 入门及渐进 16.1 -- C 代码实现CRC32校验函数】

请阅读【嵌入式开发学习必备专栏】 文章目录 CRC32校验函数CRC32 表与函数CRC32 测试函数测试结果 对比测试结果 CRC32校验函数 在C语言中&#xff0c;实现CRC32计算的函数需要一个CRC算法的实现。以下是一个使用查表法实现CRC32的简单例子。这种方法通过预先计算好的CRC表来快…

推导 模型矩阵的逆转置矩阵求运动物体的法向量

一个物体表面的法向量如何随着物体的坐标变换而改变&#xff0c;取决于变换的类型。使用逆转置矩阵&#xff0c;可以安全地解决该问题&#xff0c;而无须陷入过度复杂的计算中。 法向量变化规律 平移变换不会改变法向量&#xff0c;因为平移不会改变物体的方向。 旋转变换会改…

Excel办公技巧之下拉菜单

在日常办工中&#xff0c;经常需在单元格中输入特定的值&#xff0c;此时我们可以使用下拉菜单解决&#xff0c;输入错误和错误值&#xff0c;可以一劳永逸的解决固定数据输入问题。 使用Excel下拉菜单时&#xff0c;它在数据输入和验证方面发挥着重要作用通过点击单元格的下拉…

Mp3tag for Mac:音乐标签,轻松管理

还在为杂乱无章的音乐文件而烦恼吗&#xff1f;Mp3tag for Mac&#xff0c;让您的音乐库焕然一新&#xff01;它支持多种音频格式&#xff0c;批量编辑标签&#xff0c;让音乐管理变得简单高效。同时&#xff0c;自动获取在线数据库的音乐元数据&#xff0c;确保您的音乐库始终…

8种区块链开发者必须知道的顶级编程语言!

我来问你一个问题&#xff1a;请说出一种技术&#xff0c;它以去中心化、不可篡改和透明性等核心特征席卷了全球。 这个问题的答案是&#xff0c;当然是区块链&#xff0c;它在近些年进入大家的视野并颠覆了工商业&#xff0c;没有任何其他技术能够做到这一点。 预计从2020年…

Linux-vi、vim

使用Xshell远程登录到Linux主机进行操作 命令行不用全部掌握&#xff0c; 一般编辑大文件&#xff0c;比较复杂的情况下&#xff0c; 我们还是使用Xftp工具&#xff0c; down下来再恢复回去。

1065: 无向图的连通分量计算

解法&#xff1a; dfs求连通性 1.设节点表vis[] 2.遍历节点表dfs标记&#xff0c;每次得到一个连通分量 #include<iostream> #include<vector> using namespace std; int arr[100][100]; void dfs(vector<bool>& vis, int v) {//不用终止条件&#x…

day10-Set集合

1.Set 那接下来我们来看Collection单列集合体系的第二部分 Set集合。 1.1 Set集合概述和特点 Set集合特点 1.可以去除重复 2.存取顺序不一致 3.没有带索引的方法&#xff0c;所以不能使用普通fori循环遍历&#xff0c;也不能通过索引来获取&#xff0c;删除Set集合里面的元…

WebSocket 详解加入门实操理解加深

WebSocket 介绍 WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c; 并进行双向数据传输。 HTTP协议和WebSocket协议对比&#xff1a; HTTP是短连接…

基于SpringBoot的竹宣非遗宣传网站

摘要 随着互联网的普及和数字化时代的到来&#xff0c;竹编等非物质文化遗产的保护与传承面临新的机遇和挑战。该研究旨在使用SpringBoot后端框架与Vue前端框架&#xff0c;构建一个竹编非遗宣传网站&#xff0c;通过丰富的展示形式和交互体验&#xff0c;提升公众对竹编这一非…

怎么解决端口被占用

目录 一、引言 二、解决方法 一、引言 最近用vscode写网页&#xff0c;老是遇见端口被占用&#xff0c;报错如下&#xff1a; listen tcp :8080: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted. 二、解决方法 1.换…

OpenHarmony 实战开发 - 如何在源码中编译复杂应用(4.0-Release)

文档环境 开发环境&#xff1a;Windows 11 编译环境&#xff1a;Ubuntu 22.04 开发板型号&#xff1a;DAYU 200&#xff08;RK3568&#xff09; 系统版本&#xff1a;OpenHarmony-4.0-Release 功能简介 在 OpenHarmony 系统中预安装应用的 hap 包会随系统编译打包到镜像中&a…

数字水印 | 基于小波变换的数字水印技术

&#x1f34d;原文&#xff1a; 基于小波变换的数字水印技术 &#x1f34d;写在前面&#xff1a; 本文属搬运博客&#xff0c;自己留存学习。 正文 小波变换 把一个信号分解成由基本小波经过移位和缩放后的一系列小波&#xff0c;它是一种 “时间——尺度” 信号的多分辨率分…