不可变集合、Stream流、方法引用

一、不可变集合

是一个长度不可变,内容也无法修改的集合

定义完成后不可以修改,或者添加、删除

不可变集合分类

  • 不可变的list集合

  • 不可变的set集合

  • 不可变的map集合

如何创建不可变集合?
        List、Set、Map接口中,都存在of方法可以创建不可变集合

三种方式的细节

  • List:直接用
  • Set:元素不能重复
  • Map:元素不能重复、键值对数量最多是10个。

                                超过10个用ofEntries方法,JDK10以后出了一个Map.copyof(hm)方法,直接就可以使用了

 List<String> list = List.of("张三", "李四", "王五", "赵六");
 Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六"); Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六");
Map<String, String> map = Map.of("张三", "南京", "张三", "北京", "王五", "上海","赵六", "广州", "孙七", "深圳", "周八", "杭州","吴九", "宁波", "郑十", "苏州", "刘一", "无锡","陈二", "嘉兴");

        //获取到所有的键值对对象(Entry对象)Set<Map.Entry<String, String>> entries = hm.entrySet();//把entries变成一个数组Map.Entry[] arr1 = new Map.Entry[0];//toArray方法在底层会比较集合的长度跟数组的长度两者的大小//如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组//如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用Map.Entry[] arr2 = entries.toArray(arr1);//不可变的map集合Map map = Map.ofEntries(arr2);//或者
Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));//或者
Map<String, String> map = Map.copyOf(hm);

二、Stream流

结合Lambda表达式,简化集合数组的操作

使用步骤:

1.先得到一条Stream流(流水线),并把数据放上去
2.利用Stream流中的API进行各种操作
过滤、转换        中间方法            方法调用完毕之后,还可以调用其他方法

统计、打印        终结方法            最后一步,调用完毕之后,不能调用其他方法
2.使用中间方法对流水线上的数据进行操作
3.使用终结方法对流水线上的数据进行操作


   1.获取Stream流

获取方式方法名说明
单列集合default Stream<E> stream()collection中的默认方法
双列集合先使用keySet ()
entrySet ()
获取单列集合
无法直接使用stream流
数组public static <T> Stream<T> stream(T[]array)Arrays工具类中的静态方法
一堆零散数据public static<T> Stream<T> of(T... values)Stream接口中的静态方法
public class StreamDemo {public static void main(String[] args) {//Collection体系的集合可以使用默认方法stream()生成流List<String> list = new ArrayList<String>();Stream<String> listStream = list.stream();Set<String> set = new HashSet<String>();Stream<String> setStream = set.stream();//Map体系的集合间接的生成流Map<String,Integer> map = new HashMap<String, Integer>();Stream<String> keyStream = map.keySet().stream();Stream<Integer> valueStream = map.values().stream();Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();//数组可以通过Arrays中的静态方法stream生成流String[] strArray = {"hello","world","java"};Stream<String> strArrayStream = Arrays.stream(strArray);//同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");Stream<Integer> intStream = Stream.of(10, 20, 30);}
}

2.Stream流中间操作方法

方法名说明
Stream<T> filter(Predicate predicate)过滤
Stream<T> limit(long maxSize)获取前几个元素
Stream<T> skip(long n)跳过前几个元素
static <T> Stream<T> concat(Stream a, Stream b)合并a和b两个流为一个流
Stream<T> distinct()元素去重,依赖(hashCode和equals方法)
Stream<R> map(Function<T , R> mapper)转换流中的数据类型

注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据
filter代码演示

public class MyStream3 {public static void main(String[] args) {
//        Stream<T> filter(Predicate predicate):过滤
//        Predicate接口中的方法	boolean test(T t):对给定的参数进行判断,返回一个布尔值ArrayList<String> list = new ArrayList<>();list.add("张三丰");list.add("张无忌");list.add("张翠山");list.add("王二麻子");list.add("张良");list.add("谢广坤");//filter方法获取流中的 每一个数据.//而test方法中的s,就依次表示流中的每一个数据.//我们只要在test方法中对s进行判断就可以了.//如果判断的结果为true,则当前的数据留下//如果判断的结果为false,则当前数据就不要.
//        list.stream().filter(
//                new Predicate<String>() {
//                    @Override
//                    public boolean test(String s) {
//                        boolean result = s.startsWith("张");
//                        return result;
//                    }
//                }
//        ).forEach(s-> System.out.println(s));//因为Predicate接口中只有一个抽象方法test//所以我们可以使用lambda表达式来简化
//        list.stream().filter(
//                (String s)->{
//                    boolean result = s.startsWith("张");
//                        return result;
//                }
//        ).forEach(s-> System.out.println(s));list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s));}
}

limit&skip代码演示

public class StreamDemo02 {public static void main(String[] args) {//创建一个集合,存储多个字符串元素ArrayList<String> list = new ArrayList<String>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");//需求1:取前3个数据在控制台输出list.stream().limit(3).forEach(s-> System.out.println(s));System.out.println("--------");//需求2:跳过3个元素,把剩下的元素在控制台输出list.stream().skip(3).forEach(s-> System.out.println(s));System.out.println("--------");//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出list.stream().skip(2).limit(2).forEach(s-> System.out.println(s));}
}

concat&distinct代码演示

public class StreamDemo03 {public static void main(String[] args) {//创建一个集合,存储多个字符串元素ArrayList<String> list = new ArrayList<String>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");//需求1:取前4个数据组成一个流Stream<String> s1 = list.stream().limit(4);//需求2:跳过2个数据组成一个流Stream<String> s2 = list.stream().skip(2);//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
//        Stream.concat(s1,s2).forEach(s-> System.out.println(s));//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s));}
}

3.Stream流终结操作方法

方法名说明
void forEach(Consumer action)遍历
long count()统计个数
toArray()收集流中数据,放到数组中
collect(Collector  collector)收集流中数据,放到集合中
public class MyStream5 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三丰");list.add("张无忌");list.add("张翠山");list.add("王二麻子");list.add("张良");list.add("谢广坤");//method1(list);//        long count():返回此流中的元素数long count = list.stream().count();System.out.println(count);}private static void method1(ArrayList<String> list) {//  void forEach(Consumer action):对此流的每个元素执行操作//  Consumer接口中的方法void accept(T t):对给定的参数执行此操作//在forEach方法的底层,会循环获取到流中的每一个数据.//并循环调用accept方法,并把每一个数据传递给accept方法//s就依次表示了流中的每一个数据.//所以,我们只要在accept方法中,写上处理的业务逻辑就可以了.list.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});System.out.println("====================");//lambda表达式的简化格式//是因为Consumer接口中,只有一个accept方法list.stream().forEach((String s)->{System.out.println(s);});System.out.println("====================");//lambda表达式还是可以进一步简化的.list.stream().forEach(s->System.out.println(s));}
}

collection应用:

// toList和toSet方法演示 
public class MyStream7 {public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();for (int i = 1; i <= 10; i++) {list1.add(i);}list1.add(10);list1.add(10);list1.add(10);list1.add(10);list1.add(10);//filter负责过滤数据的.//collect负责收集数据.//获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.//Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.List<Integer> list = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());System.out.println(list);Set<Integer> set = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toSet());System.out.println(set);
}
}
/**
Stream流的收集方法 toMap方法演示
创建一个ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年龄
"zhangsan,23"
"lisi,24"
"wangwu,25"
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
*/
public class MyStream8 {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> map = list.stream().filter(s -> {String[] split = s.split(",");int age = Integer.parseInt(split[1]);return age >= 24;}//   collect方法只能获取到流中剩余的每一个数据.//在底层不能创建容器,也不能把数据添加到容器当中//Collectors.toMap 创建一个map集合并将数据添加到集合当中// s 依次表示流中的每一个数据//第一个lambda表达式就是如何获取到Map中的键//第二个lambda表达式就是如何获取Map中的值).collect(Collectors.toMap(s -> s.split(",")[0],s -> Integer.parseInt(s.split(",")[1]) ));System.out.println(map);}
}

总结:

1. Stream流的作用
结合了Lambda表达式,简化集合、数组的操作

2. Stream的使用步骤
获取Stream流对象使用中间方法处理数据●使用终结方法处理数据

3.如何获取Stream流对象

  • 单列集合:Collection中的默认方法stream
  • 双列集合:不能直接获取
  • 数组: Arrays工具类型中的静态方法stream
  • 一堆零散的数据:Stream接口中的静态方法of

4.常见方法
中间方法:
filter,limit,skip, distinct,concat,map
终结方法:
forEach,count,collect


三、方法引用

1.什么是方法引用?
把已经存在的方法拿过来用,当做函数式接口中抽象方法的方法体
2.︰︰是什么符号?
方法引用符
3.方法引用时要注意什么?

  • 需要有函数式接口
  • 被引用方法必须已经存在
  • 被引用方法的形参和返回值需要跟抽象方法保持一致
  • 被引用方法的功能要满足当前的需求

4.方法引用的分类

  1. 引用静态方法 
  2. 引用成员方法
  • 引用其他类的成员方法
  • 引用本类的成员方法
  • 引用父类的成员方

        3.引用构造方法

        4.其他调用方式

  • 使用类名引用成员方法
  • 引用数组的构造方法

1.引用静态方法


类名::静态方法

package com.itheima.a01myfunction;import java.util.ArrayList;
import java.util.Collections;public class FunctionDemo2 {public static void main(String[] args) {/*方法引用(引用静态方法)格式类::方法名需求:集合中有以下数字,要求把他们都变成int类型"1","2","3","4","5"*///1.创建集合并添加元素ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"1","2","3","4","5");//2.把他们都变成int类型/* list.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {int i = Integer.parseInt(s);return i;}}).forEach(s -> System.out.println(s));*///1.方法需要已经存在//2.方法的形参和返回值需要跟抽象方法的形参和返回值保持一致//3.方法的功能需要把形参的字符串转换成整数list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));}
}

2.引用成员方法


对象∶:成员方法

this: :成员方法

super: :成员方法

package com.itheima.a01myfunction;import java.util.ArrayList;
import java.util.Collections;public class FunctionDemo3  {public static void main(String[] args) {/*方法引用(引用成员方法)格式其他类:其他类对象::方法名本类:this::方法名(引用处不能是静态方法)父类:super::方法名(引用处不能是静态方法)需求:集合中有一些名字,按照要求过滤数据数据:"张无忌","周芷若","赵敏","张强","张三丰"要求:只要以张开头,而且名字是3个字的*///1.创建集合ArrayList<String> list = new ArrayList<>();//2.添加数据Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");//3.过滤数据(只要以张开头,而且名字是3个字的)//list.stream().filter(s->s.startsWith("张")).filter(s->s.length() == 3).forEach(s-> System.out.println(s));/*  list.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {return s.startsWith("张") && s.length() == 3;}}).forEach(s-> System.out.println(s));*//*  StringOperation so = new StringOperation();list.stream().filter(so::stringJudge).forEach(s-> System.out.println(s));*///静态方法中是没有this的list.stream().filter(new FunctionDemo3()::stringJudge).forEach(s-> System.out.println(s));}public boolean stringJudge(String s){return s.startsWith("张") && s.length() == 3;}
}

3.引用构造方法


类名: : new

package com.itheima.a01myfunction;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;public class FunctionDemo4 {public static void main(String[] args) {/*方法引用(引用构造方法)格式类名::new目的:创建这个类的对象需求:集合里面存储姓名和年龄,要求封装成Student对象并收集到List集合中方法引用的规则:1.需要有函数式接口2.被引用的方法必须已经存在3.被引用方法的形参和返回值,需要跟抽象方法的形参返回值保持一致4.被引用方法的功能需要满足当前的需求*///1.创建集合对象ArrayList<String> list = new ArrayList<>();//2.添加数据Collections.addAll(list, "张无忌,15", "周芷若,14", "赵敏,13", "张强,20", "张三丰,100", "张翠山,40", "张良,35", "王二麻子,37", "谢广坤,41");//3.封装成Student对象并收集到List集合中//String --> Student/*  List<Student> newList = list.stream().map(new Function<String, Student>() {@Overridepublic Student apply(String s) {String[] arr = s.split(",");String name = arr[0];int age = Integer.parseInt(arr[1]);return new Student(name, age);}}).collect(Collectors.toList());System.out.println(newList);*/List<Student> newList2 = list.stream().map(Student::new).collect(Collectors.toList());System.out.println(newList2);}
}

4.使用类名引用成员方法


类名::成员方法

package com.itheima.a01myfunction;import java.util.ArrayList;
import java.util.Collections;public class FunctionDemo5 {public static void main(String[] args) {/*方法引用(类名引用成员方法)格式类名::成员方法需求:集合里面一些字符串,要求变成大写后进行输出方法引用的规则:1.需要有函数式接口2.被引用的方法必须已经存在3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。4.被引用方法的功能需要满足当前的需求抽象方法形参的详解:第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法局限性:不能引用所有类中的成员方法。是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法。*///1.创建集合对象ArrayList<String> list = new ArrayList<>();//2.添加数据Collections.addAll(list, "aaa", "bbb", "ccc", "ddd");//3.变成大写后进行输出//map(String::toUpperCase)//拿着流里面的每一个数据,去调用String类中的toUpperCase方法,方法的返回值就是转换之后的结果。list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s));//String --> String/* list.stream().map(new Function<String, String>() {@Overridepublic String apply(String s) {return s.toUpperCase();}}).forEach(s -> System.out.println(s));*/}
}

5.引用数组的构造方法


数据类型::new

package com.itheima.a01myfunction;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;public class FunctionDemo6 {public static void main(String[] args) {/*方法引用(数组的构造方法)格式数据类型[]::new目的:创建一个指定类型的数组需求:集合中存储一些整数,收集到数组当中细节:数组的类型,需要跟流中数据的类型保持一致。*///1.创建集合并添加元素ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 1, 2, 3, 4, 5);//2.收集到数组当中Integer[] arr2 = list.stream().toArray(Integer[]::new);System.out.println(Arrays.toString(arr2));/*Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {@Overridepublic Integer[] apply(int value) {return new Integer[value];}});*///3.打印}
}


 

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

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

相关文章

k8s的ClusterIP和NodePort类型有何不同

Kubernetes&#xff08;K8s&#xff09;是一个开源的容器编排平台&#xff0c;用于自动部署、扩展和管理容器化应用程序。在Kubernetes中&#xff0c;服务&#xff08;Service&#xff09;是一个抽象层&#xff0c;它定义了一种访问Pods&#xff08;运行中的容器&#xff09;的…

备战蓝桥杯---贪心刷题1

话不多说&#xff0c;直接看题&#xff1a; 本质是一个数学题&#xff1a; 我们令xi<0表示反方向传递&#xff0c;易得我们就是求每一个xi的绝对值之和min,我们令平均值为a爸。 易得约束条件&#xff1a; x1-x2a1-a,x2-x3a2-a..... 解得x1x1-0,x2x1-((n-1)*a-a2-...an)。…

LLM - 大语言模型 基于人类反馈的强化学习(RLHF)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/137269049 基于人类反馈的强化学习(RLHF,Reinforcement Learning from Human Feedback),结合 强化学习(RL) 和 人类反馈 来优化模型的性能。这种方法主要包…

pair作为unordered_map的key报错

问题 pair作为unordered_map的key报错&#xff0c;编译时会报错 原因 因为pair没有哈希函数 解决方法 定义哈希函数 template <typename T> inline void hash_combine(std::size_t &seed, const T &val) {seed ^ std::hash<T>()(val) 0x9e3779b9 (…

Jamba: A Hybrid Transformer-Mamba Language Model

Jamba: A Hybrid Transformer-Mamba Language Model 相关链接&#xff1a;arXiv 关键字&#xff1a;hybrid architecture、Transformer、Mamba、mixture-of-experts (MoE)、language model 摘要 我们介绍了Jamba&#xff0c;一种新的基于新颖混合Transformer-Mamba混合专家&am…

xilinx fpga程序固化

一、前言 xilinx 旗下的产品主要有包含有处理器的SOC系列&#xff0c;也有只有纯逻辑的fpga&#xff0c;两者的程序固化的方法并不相同&#xff0c;本文介绍只包含纯逻辑而不涉及处理器的fpga的代码固化。 二、固化流程 将工程综合&#xff0c;实现&#xff0c;并得到比特流…

MYSQL-7.内存

内存 Mysql的内存结构 大体可分为四个板块&#xff1a;mysql工作组件、线程本地内存、mysql共享内存、存储引擎缓冲区&#xff1b; Mysql server工作组件 对应着mysql架构图中的组件层&#xff1a; Mysql在启动时&#xff0c;会将这些工作组件初始化到内存中&#xff1b; …

MSSQL有关数据库、表的循环操作可使用的存储过程 sp_MSforeachdb 及 sp_MSforeachtable

MSSQL有关数据库、表的循环操作可使用的存储过程: 1. sp_MSforeachdb command1print ?, command2DBCC CHECKDB(?) --检查所有的数据库 2. sp_MSforeachtable command1print ?, command2sp_spaceused ? --统计各个表的空间使用情况 ​ 【说明】sys.​sp_MSforeachdb 和 …

【LAMMPS学习】七、加速性能(2)性能测试

7. 加速性能 7.1.基准测试 7.2.性能测试 在尝试让模拟运行得更快之前&#xff0c;您应该了解它当前的执行情况以及瓶颈所在。 做到这一点的最佳方法是在几个不同的处理器计数&#xff08;如果可能的话&#xff0c;包括单个处理器&#xff09;上运行您的系统&#xff08;实际…

【Vscode】无法将“python,pip,node,npm等”识别为cmdlet...问题

问题出现场景 新换个电脑&#xff0c;然后重新安装了软件&#xff0c;又复现一次又一次“老生常谈”的问题。 解决方法 网络答案吧五花八门&#xff0c;我采取一个我的场景解决可行的方案&#xff0c; 首先我的场景是&#xff0c;环境变量&#xff0c;配置路径都是没有问题…

抖音视频关键词批量下载工具|视频爬虫采集软件

抖音视频批量提取工具&#xff0c;搜索即下载&#xff0c;轻松获取所需视频&#xff01; 正文&#xff1a; 想要轻松获取抖音上的精彩视频吗&#xff1f;现在&#xff0c;有了我们的抖音视频批量提取工具&#xff0c;一切变得简单易行&#xff01;Q:290615413无论是针对特定关…

Nginx中间件服务:负载均衡(调度算法)

文章目录 引言I 原理1.1 后端服务器在负载均衡调度中的状态1.2 调度算法II upstreamd的应用2.1 加权负载均衡的服务器列表2.2 AB测试中使用upstream切分流量2.3 基于URL的HASH2.4 IP_HASHsee also引言 作用 转发功能:按照一定的调度算法(轮询、权重)将客户端发来的请求转发…

策略模式

定义&#xff1a; 策略模式定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使他们可以相互替换&#xff0c;且算法的变化不会影响到使用算法的客户。 优点&#xff1a; 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。 缺点&#xff1a; 1、策…

基于Pytorch+昇腾NPU部署baichuan2-7B大模型

一、模型介绍 Baichuan 2 是百川智能推出的新一代开源大语言模型&#xff0c;采用 2.6 万亿 Tokens 的高质量语料训练。Baichuan 2 在多个权威的中文、英文和多语言的通用、领域 benchmark 上取得同尺寸最佳的效果。 它基于 Transformer 结构&#xff0c;在大约1.2万亿 tokens…

c++20协程详解(一)

前言 本文是c协程第一篇&#xff0c;主要是让大家对协程的定义&#xff0c;以及协程的执行流有一个初步的认识&#xff0c;后面还会出两篇对协程的高阶封装。 在开始正式开始协程之前&#xff0c;请务必记住&#xff0c;c协程 不是挂起当前协程&#xff0c;转而执行其他协程&a…

el-table\vxe-table深色背景Css样式

一、el-table 1、HTML <div class"table"><el-table:data"tableData":cell-class-name"tabCellClassName":row-class-name"tabRowClassName"border><!-- 序号 --><el-table-column type"index" labe…

pygame--坦克大战(二)

加载敌方坦克 敌方坦克的方向是随机的&#xff0c;使用随机数生成。 初始化敌方坦克。 class EnemyTank(Tank):def __init__(self,left,top,speed):self.images {U: pygame.image.load(img/enemy1U.gif),D: pygame.image.load(img/enemy1D.gif),L: pygame.image.load(img/e…

Golang基础-9

Go语言基础 介绍 基础 结构体 自定义类型 结构体定义 结构体声明 结构体初始化 字段访问与修改 匿名结构体 结构体嵌套 初始化函数定义 介绍 本文介绍Go语言中自定义类型、结构体定义、结构体声明、结构体初始化、字段访问与修改、匿名结构体、结构体嵌套、初始化…

clickhouse sql使用2

1、多条件选择 multiIf(cond_1, then_1, cond_2, then_2, …, else) select multiIf(true,0,1) 当第一条件不成立看第二条件判断 第一个参数条件参数&#xff0c;第二参数条件成立时走 2、clickhouse 在计算时候长出现NaN和Infinity异常处理 isNaN()和isInfinite()处理

免费图片转excel方案大全

随着信息技术的发展&#xff0c;我们经常会遇到需要将图片中的数据转换成Excel表格的情况。这种需求在数据分析、报表制作、信息整理等领域尤为常见。然而&#xff0c;许多人在面对这一任务时感到困惑&#xff0c;不知道如何进行。本文将为大家介绍几种免费的图片转Excel方案&a…