JDK8特性,Lambda,时间日期,接口增强,Optional,Stream流

目录

JDK8

Lambda

概述

特点

语法

几种基本的写法

方法的引用

几种常见方式

 常见的函数式接口

Supplier 生产数据

Consumer 消费数据

 Function

Predicate

LocalDate&LocalTime&LocalDateTime

jdk7日期时间存在的问题

设计不合理

时间格式化和解析操作线程不安全

无法直接处理时区,针对时区的操作比较麻烦

jdk8提供了一套全新的时间日期API

LocalDate

LocalTime

LocalDateTime

DateTimeFormatter

ZonedDateTime

Instant

Duration

Period

时间校正器

接口增强

Optional

概述

获取Optional

常用方法

不常用方法

Stream流

概述

特点

方法

Stream流的获取

中间方法

filter,过滤

map,转换

distinct,去重

limit,截取

skip,跳过

sorted,排序

peek,执行操作

concat,合并

终结方法

forEach,遍历

count,计数

match,条件判断

find,查找

reduce,聚合

min

max

流中数据接收

用集合接收Stream流中数据

转为map的一些处理场景

用数组接收Stream流中数据

另一种聚合方式

mapToInt,转换

流中数据的分组

流中数据分区

流中数据拼接

问题

Stream串行流和并行流

获取并行流

并行流的线程安全问题

并行流的原理

核心思想


JDK8

JDK8是java第一个LTS长期支持版本,2014年发布,是最成功,应用最广泛的版本,JDK8目前计划更新到2030年,虽然JDK已经有了新的LTS版本JDK11,JDK17,JDK21,使用JDK8的项目仍然广泛存在

Lambda

概述

jdk8引入了一个新的操作符 lambda操作符 ->

操作符左侧:lambda参数列表,右侧:lambda函数体

可以理解为可传递的匿名函数,即传递函数体并生成对象,可以简化匿名内部类的使用

需要函数式接口的支持

        函数式接口:接口中只有一个抽象方法

        可以用@FunctionalInterface注解给接口做检查,如果接口有多个抽象方法,会语法报错

特点

函数没有名称,有参数列表,函数体,返回类型,可抛出的异常列表

参数列表不需要声明类型,lambda可以根据上下文推断类型

语法

有无返回值:单行情况下,函数体的整体就是返回值;多行情况下,return返回值

函数体为多行时用{}括起来

几种基本的写法
无参,无返回值
Runnable r1 = () -> System.out.println("lambda");
r1.run();
有一个参数,无返回值
x -> System.out.println(x); 
有两个参数,有返回值
(x, y) -> x + y
如果是多行函数体,加上{}
Runnable r1 = () -> {System.out.println("lambda111");System.out.println("lambda222");System.out.println("lambda333");
};
r1.run();
SumFunction<Integer> sumObj= (x, y) -> {int a = x;int b = y;return a + b;
};
System.out.println(sumObj.sum(1, 2));

方法的引用

作用:解决使用lambda时重复定义类似方法的问题,减少冗余

语法格式:方法引用运算符,::(双冒号),接口方法的返回值和参数列表要和被传递方法保持一致

几种常见方式

类::静态方法名

Comparator bb = Integer::compare;

将Integer的compare方法传递给Comparator的唯一抽象方法

类::实例方法名

StringFunction obj = String::equals;

将String的equals方法传递给StringFunction的唯一抽象方法

对象::实例方法名

Runnable r1 = student::study

将Student的study方法传递给Runnable的唯一抽象方法

通过 类名::new 构造器的引用,创建一个引用

可以是无参,有参构造,自动上下文推断

接口的方法要和构造方法的返回值,参数列表保持一致

StudentFunction stuObj = Student::new

将Student的构造方法传递给StudentFunction的唯一抽象方法

xxx[]::new 数组构造器,需要给定数组长度

@PostMapping("/jdk8TestMethods")
@ApiOperation(value = "方法引用测试")
public ResponseResult jdk8TestMethods() {//类名::普通方法Function<String, Integer> function = String::length;//类名::静态方法Function<Integer, String> function1 = String::valueOf;//类名::newBiFunction<String, Integer, StudentVO> function2 = StudentVO::new;//[]::newFunction<Integer, String[]> function3 = String[]::new;System.out.println(function.apply("function"));System.out.println(function1.apply(211).substring(0, 1));System.out.println(function2.apply("张三", 25));System.out.println(function3.apply(3).length);return new ResponseResult().resultFlag(true);
}

 常见的函数式接口

jdk提供这些函数式接口,方便开发者使用lambda表达式

Supplier 生产数据

无参有返回值,泛型为<返回值类型>

@PostMapping("/jdk8TestSupplier")
@ApiOperation(value = "jdk8TestSupplier")
public ResponseResult jdk8TestSupplier() {System.out.println(testSupplier(() -> 1 + 2));return new ResponseResult().resultFlag(true);
}private Integer testSupplier(Supplier<Integer> supplier) {return supplier.get();
}
Consumer 消费数据

有参无返回值,泛型为<入参类型>

andThen(),用于多个consumer先后执行

@PostMapping("/jdk8TestConsumer")
@ApiOperation(value = "jdk8TestConsumer")
public ResponseResult jdk8TestConsumer() {testConsumer(message -> System.out.println(message.toUpperCase()), "Hello World!");testConsumer2(message -> System.out.println(message.toUpperCase()), message -> System.out.println(message.toLowerCase()), "Hello World!");return new ResponseResult().resultFlag(true);
}private void testConsumer(Consumer<String> consumer, String str) {consumer.accept(str);
}private void testConsumer2(Consumer<String> consumer1, Consumer<String> consumer2, String str) {consumer1.andThen(consumer2).accept(str);
}
 Function

有参有返回值,根据一个数据,得到另一个数据

泛型为<入参类型,返回值类型>

apply()

andThen()

@PostMapping("jdk8TestFunction")
@ApiOperation(value = "jdk8TestFunction")
public ResponseResult jdk8TestFunction() {Integer integer = testFunction((msg) -> msg.length(), (intValue -> intValue * 2), "function");System.out.println(integer);return new ResponseResult().resultFlag(true);
}private Integer testFunction(Function<String, Integer> function1, Function<Integer, Integer> function2, String str) {return function1.andThen(function2).apply(str);
}
Predicate

有参有返回值,返回值为Boolean,泛型为<入参类型>

@PostMapping("/jdk8TestPredicate")
@ApiOperation(value = "jdk8TestPredicate")
public ResponseResult jdk8TestPredicate() {testPredicate((msg) -> msg.startsWith("pre"),(msg) -> msg.endsWith("hh"),"predicate");return new ResponseResult().resultFlag(true);
}private void testPredicate(Predicate<String> predicate1, Predicate<String> predicate2, String str) {//andBoolean boolean1 = predicate1.and(predicate2).test(str);//orBoolean boolean2 = predicate1.or(predicate2).test(str);//negateBoolean boolean3 = predicate1.negate().test(str);System.out.println(boolean1);System.out.println(boolean2);System.out.println(boolean3);
}

LocalDate&LocalTime&LocalDateTime

jdk7日期时间存在的问题

设计不合理

Date存在1900的偏移量,不能直接获取某个时刻

util和sql包都有Date类,util包的Date类包含日期时间,sql包的Date类只包含日期,负责格式化和解析日期时间的类在text包下

时间格式化和解析操作线程不安全
无法直接处理时区,针对时区的操作比较麻烦
//1900偏移量
Date date = new Date(2021, 06, 25);
System.out.println(date);
//Mon Jul 25 00:00:00 CST 3921

jdk8提供了一套全新的时间日期API

java.time包下

线程安全,时间日期对象不可变,修改的操作是会生成一个新的值

可以直接处理时区

可以通过预定义处理日期时间

LocalDate

创建
//指定日期2021-06-25
LocalDate localDate = LocalDate.of(2021, 6, 25);
//当前日期2021-06-25
LocalDate localDate1 = LocalDate.now();
获取
//获取年月日
int year = localDate.getYear();
//月份是枚举类型
int month1 = localDate.getMonth().getValue();
int month2 = localDate.getMonthValue();
//周几是枚举类型,周几就对应几,如周一,则value为1,周日value为7
int dayOfWeek1 = localDate.getDayOfWeek().getValue();
System.out.println(dayOfWeek1);
//几日是int类型
int dayOfMonth1 = localDate.getDayOfMonth();
int dayOfYear1 = localDate.getDayOfYear();

LocalTime

创建
//指定11:39:31.111111111
LocalTime localTime = LocalTime.of(11, 39, 31,111111111);
//当前11:59:33.754
LocalTime localTime1 = LocalTime.now();
获取
localTime.getHour();
localTime.getMinute();
localTime.getMinute();
localTime.getNano();

LocalDateTime

创建
LocalDateTime localDateTime = LocalDateTime.of(2021,6,25,13,48,1,11111);
LocalDateTime localDateTime1 = LocalDateTime.now();
获取
localDateTime.getYear();
修改日期时间:LocalDateTime提供的修改操作,实际上并没有修改原本的对象,而是进行了副本拷贝,这样就解决了线程安全的问题
直接修改为指定值
LocalDateTime localDateTime2 = localDateTime.withYear(2022);
localDateTime.withDayOfMonth(26);
localDateTime.withDayOfYear(200);
加减
LocalDateTime localDateTime3 = localDateTime.plusYears(1);
LocalDateTime localDateTime4 = localDateTime.minusYears(1);
比较日期时间
boolean after = localDateTime.isAfter(localDateTime1);
boolean before = localDateTime.isBefore(localDateTime1);
boolean equal = localDateTime.isEqual(localDateTime1);

DateTimeFormatter

格式化和解析

指定格式
//系统预定义格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//自定义格式
DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
时间日期转字符串
//2021-06-25T18:26:15.068
String format1 = localDateTime1.format(dateTimeFormatter);
//2021-06-25 18:26:15
String format2 = localDateTime1.format(dateTimeFormatter1);
字符串转日期时间
LocalDateTime parseLocalDateTime = LocalDateTime.parse("2021-6-25 18:34:00", dateTimeFormatter1);

ZonedDateTime

时区操作
//获取所有时区ID
ZoneId.getAvailableZoneIds();
//获取当前时间,东八区,比格林尼治时间早8h
LocalDateTime localDateTime = LocalDateTime.now();
//标准时间
ZonedDateTime zonedDateTime = ZonedDateTime.now(Clock.systemUTC());
//系统默认时区
ZonedDateTime zonedDateTime1 = ZonedDateTime.now();
//指定时区
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("America/Marigot"));

Instant

时间戳类,从1970.1.1起始,精确到纳秒

Instant instant = Instant.now();
instant.getNano();

Duration

计算时间差LocalTime

LocalTime localTime1 = LocalTime.now();
LocalTime localTime2 = LocalTime.of(11, 0, 0);
Duration duration = Duration.between(localTime1, localTime2);
//        localTime2-localTime1
System.out.println(duration.toHours());
System.out.println(duration.toMinutes());
System.out.println(duration.toMillis());
System.out.println(duration.toNanos());

Period

计算日期差LocalDate

LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2020, 1, 1);
Period period = Period.between(localDate2, localDate1);
period.getYears();
period.getMonths();
period.getDays();

时间校正器

调整时间

自定义校正规则/使用系统预定义校正规则

TemporalAdjuster adjuster = (temporal) -> {LocalDateTime localDateTime1 = (LocalDateTime) temporal;LocalDateTime localDateTime2 = localDateTime1.plusMonths(1).withDayOfMonth(1);return localDateTime2;
};LocalDateTime localDateTime = LocalDateTime.now();
//自定义
LocalDateTime localDateTime1 = localDateTime.with(adjuster);
//系统预定义
LocalDateTime localDateTime2 = localDateTime.with(TemporalAdjusters.firstDayOfNextMonth());

接口增强

JDK8给接口提供了增强

接口可以给定默认实现,使用default关键字

        修饰符 default 返回值类型 xxx() {...}

        default soutXxx() {sout("xxx");}

对于静态方法,可以通过接口名直接调用

        修饰符 static 返回值类型 xxx() {"xxx"}

        static void soutXxx() {System.out.println("xxx");}

Optional

概述

Optional是工具类,没有任何子类

Optional是一个可以为null的容器,保存null时表示值不存在

作用:避免显式的进行null检查,防止NullPointException

获取Optional

Optional.of(T t) 不支持null,即t必须非空

Optional.ofNullable(T t) 支持null,即t可以为空

Optional.empty() 直接获取一个空的Optional,可以指定其中的数据类型

Optional<String> optional1 = Optional.of("name");
Optional<String> optional2 = Optional.ofNullable(null);
Optional<String> optional3 = Optional.empty();

常用方法

isPresent() 判断是否包含值,包含返回true,不包含返回false

ifPresent() 判断是否包含值,包含值,就做相应操作

get() 获取容器中的值,没值则抛出NoSuchElementException

orElse(T t) 容器有值则返回该值,否则返回t,T类型只能是Optional中元素类型

orElseGet(Supplier other) 即orElseGet(()->{...}),容器有值则返回该值,否则返回lambda表达式的值

orElseThrow(Supplier exceptionSupplier) 容器有值则返回该值,否则返回异常

System.out.println(optional1.isPresent() ? optional1.get() : "000");
optional1.ifPresent(System.out::println);
System.out.println(optional1.orElse("111"));
System.out.println(optional1.orElseGet(() -> {return "222";
}));
System.out.println(optional1.orElseThrow(Exception::new));

不常用方法

Optional filter(Predicate predicate)

Optional map(Function mapper)

Optional flatMap(Function> mapper)

Stream流

概述

java API的新成员,遍历数据的高级迭代器

作用:给数组/集合的操作提供了更好的解决方式

特点

支持声明式处理集合,天然支持并行

和IO流没有任何关系,不是数据结构,不保存数据

虽然不保存数据,但Stream流对于引用型变量的操作是实际的改变

方法

Stream流的获取

集合:collection.stream()

注意:Map没有实现Collection接口,无法直接获取Stream流,操作Map要通过其key,value集合

数组:Stream.of(arr)

注意:

        这种方式的本质上是Arrays工具类的Arrays.stream

        Stream流无法操作基本数据类型的数组

@PostMapping("/testStreamCreate")
@ApiOperation(value = "获取Stream流")
public ResponseResult testStreamCreate() {ArrayList<String> arrayList = new ArrayList<>();Stream<String> streamArr = arrayList.stream();Map<String, String> map = new HashMap<>();Stream<String> stream1 = map.keySet().stream();Stream<String> stream2 = map.values().stream();Stream<Map.Entry<String, String>> stream3 = map.entrySet().stream();String[] arr = new String[10];Stream<String> streamArr = Stream.of(arr);Stream<String> streamArr2 = Arrays.stream(arr);return new ResponseResult().resultFlag(true);
}

中间方法

返回Stream本身

filter,过滤

根据条件过滤数据

list.stream().filter(str -> str.length() > 2).forEach(System.out::println);
map,转换

将流中的元素进行统一的处理,多行语句处理时,需要通过return语句将单个结果返回

list.stream().map(String::toUpperCase).forEach(System.out::println);
//多行处理语句
List<Employee> maped = employees.stream().map(e -> {e.setAge(e.getAge() + 1);e.setGender(e.getGender().equals("M")?"male":"female");return e;
}).collect(Collectors.toList());
distinct,去重

去重的依据是hashCode()和equals()

list.stream().distinct().forEach(System.out::println);
limit,截取

截取前n个数据,n>=stream.length才操作

list.stream().limit(3).forEach(System.out::println);
skip,跳过

跳过前n个数据,截取后面的流

list.stream().skip(3).forEach(System.out::println);
sorted,排序

默认根据字典顺序排序,默认升序,可以使用reversed()降序

组合使用sorted+limit+skip可以在内存中实现sql一样的分页效果

//单个属性排序
list.stream().sorted(Comparator.comparing(实体::get属性)).collect(Collectors.toList());
list.stream().sorted(Comparator.comparing(实体::get属性).reversed()).collect(Collectors.toList());
//多个属性排序
list.stream().sorted(Comparator.comparing(实体::get属性).thenComparing(实体::get属性)).collect(Collectors.toList());
//可以自定义比较方式
stream.map(Integer::parseInt).sorted((inte1, inte2) -> inte2 - inte1).forEach(System.out::println);Comparator comparator = Collator.getInstance(Locale.CHINA);
List<UpdateComponentVo> resList = stream.sorted((v1, v2) ->comparator.compare(v1.getRuleName(), v2.getRuleName())
).collect(Collectors.toList());List<Map<String, Object>> afterSort = allList.stream().sorted((o1, o2) -> {if (o1.get("UPDATETIME").toString().compareTo(o2.get("UPDATETIME").toString()) > 0) {return -1;} else {return 1;}
}).collect(Collectors.toList());//排序后进行分页
List<Map<String, Object>> pageInfo = afterSort.stream().skip((pageNum - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
peek,执行操作

没有特殊处理,直接执行lambda方法

通常不会单独使用,因为如果只是遍历并执行操作,不如使用终结方法forEach

list.stream().peek(u -> {...sout(u.getName());}
);
concat,合并

两个流合并成一个流

Stream<String> newStream = Stream.concat(stream1, stream2);

终结方法

不会返回Stream本身

注意:

        Stream不调用终结方法,那么中间操作不会执行

        Stream只能使用一次终结方法

forEach,遍历

遍历流中元素,执行方法

list.stream().forEach(System.out::println);
count,计数

获取流中元素数量

配合distinct可以判断集合中元素是否重复(去重前后的数量做对比)

long count = confList.stream().map(conf -> conf.getPropName()).distinct().count();
match,条件判断

判断数据是否符合指定条件

Boolean b1 = stream.allMatch(str -> str.length() == 1);
Boolean b2 = stream.anyMatch(str -> str.length() == 1);
Boolean b3 = stream.noneMatch(str -> str.length() == 1);
find,查找

查询流中指定元素

findFirst() 拿到流中的第一个元素

findAny() 拿到流中的任意一个元素

在串行的流中,findAny()和findFirst()返回的都是第一个对象;

在并行流(parallelStream())中,findAny返回的是最快处理完的那个线程的数据,所以并行流findAny()会比findFirst()要快

Optional<String> optional1 = stream.findFirst();
Optional<String> optional2 = stream.findAny();
reduce,聚合

将流中数据聚合成一个数据

参数有两个,参数一为初始值,参数二为运算逻辑函数

实际开发中,通常会和map一起使用

Integer integer = list.stream().map(Integer::parseInt).reduce(0, Integer::sum);
Integer integer = list.stream().map(Integer::parseInt).reduce(0, Integer::max);
Integer integer = studentSteam.map(StudentVO::getAge).reduce(0, Integer::max);
min

获取流中的最小值

Optional<Integer> optional1 = stream.map(Integer::parseInt).min(Comparator.comparingInt(i -> i));
max

获取流中的最大值

Optional<Integer> optional2 = stream.map(Integer::parseInt).max(Comparator.comparingInt(i -> i));
流中数据接收
用集合接收Stream流中数据
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
ArrayList<String> list1 = stream.collect(Collectors.toCollection(ArrayList::new));
HashSet<String> set1 = stream.collect(Collectors.toCollection(HashSet::new));
Map<String, String> map1 = stream.collect(Collectors.toMap(Person::getName,Person::getAddress,(value1, value2) -> value1));
转为map的一些处理场景

注意:当stream流中的数据存在重复,作为map的key,此时转map会失败,即并不会覆盖,而是直接报错,因此需要考虑对key的部分去重,或者重复数据处理策略

指定key-value,为对象中的某个属性值
Map<Integer, String> userMap1 = userList.stream().collect(Collectors.toMap(User::getId,User::getName));
指定key-value,为对象本身,User->User是一个返回本身的lambda表达式,Function.identity()也会返回对象本身
Map<Integer, User> userMap2 = userList.stream().collect(Collectors.toMap(User::getId,User->User));
Map<Integer, User> userMap3 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
指定key-value,为对象本身,key 冲突的解决办法,key2覆盖key1
Map<Integer, User> userMap4 = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1,key2)->key2));
拼接key->Map
Map<String, User> userMap5 = userList.stream().collect(Collectors.toMap(user -> user.getName() + user.getHobbies(), u -> u));
用数组接收Stream流中数据

String[] strArr = stream.toArray(String[]::new);

另一种聚合方式

针对集合操作:minBy,maxBy,summingInt

Optional<StudentVO> maxAgeStudent = studentSteam.collect(Collectors.maxBy(Comparator.comparingInt(StudentVO::getAge)));
Integer sumAge = studentSteam.collect(Collectors.summingInt(StudentVO::getAge));

针对数组操作,可以直接操作

Integer[] integers = {1, 2, 3, 4};
Integer sumVal = Stream.of(integers).max(Comparator.comparingInt(i -> i)).get();
mapToInt,转换

将Stream中的Integer转为int

IntStream intStream = stream.map(Integer::parseInt).mapToInt(Integer::intValue);
流中数据的分组

可以多个字段分组

//先根据age,再根据name分组
Map<Integer, Map<String, List<StudentVO>>> studentMap = studentSteam.collect(Collectors.groupingBy(StudentVO::getAge,Collectors.groupingBy(StudentVO::getName)
));//如果是List<Map>,根据某个key的值分组
Map<String, List<Map>> map = list.stream().collect(Collectors.groupingBy((Map m) -> (String)m.get("name"));
);
studentMap.forEach((k, v) -> {System.out.println(k);v.forEach((k1, v1) -> {System.out.println("\t" + k1);System.out.println("\t\t" + v1);});
});
流中数据分区
Map<Boolean, List<StudentVO>> studentMap = studentSteam.collect(Collectors.partitioningBy((student) -> student.getAge() > 22));studentMap.forEach((k, v) -> {System.out.print(k + ":");System.out.println(v);
});
流中数据拼接

可以指定分隔符,可以给拼接后的字符串增加前缀后缀

String res = stream.collect(Collectors.joining());
System.out.println(res);
String res1 = stream.collect(Collectors.joining(","));
System.out.println(res1);
String res2 = stream.collect(Collectors.joining(",", "前缀", "后缀"));
System.out.println(res2);
问题

stream流中如果要使用流外定义的数据,那么这个数据必须是final修饰,但有时候我们又必须操作一个流外数据,将这个数据放入数组中

//排序,赋值序号
Integer[] rankNum = {1};
List<RankDto> list = list.stream().sorted(Comparator.comparing(RankDto::getSumScore).reversed()).peek(RankDto -> RankDto.setRankNum(rankNum[0]++)).collect(Collectors.toList());

Stream串行流和并行流

并行流可以通过默认的ForkJoinPool采用多线程提高流操作的速度

获取并行流

通过list.parallelStream()直接获取

通过已有串行流间接获取

Stream<StudentVO> streamParallel = studentList.parallelStream(); Stream<String> streamArr = Stream.of(arr1).parallel();

并行流的线程安全问题

并行操作数据,伴随着线程安全问题,并行流如何解决线程安全问题

同步代码块

操作数据类型替换为线程安全的类型

并行流的原理

fork/join框架

包含三个模块

        线程池 ForkJoinPool

        任务对象 ForkJoinTask

        任务线程 ForkJoinWorkerThread

核心思想

分治法,工作窃取算法

大任务分为小任务,小任务的结果组合成大任务的结果

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

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

相关文章

二分类问题中评估模型的示例及释义:召准率、召回率等

1、评估参数定义 1.1、召准率&#xff08;Precision&#xff09; 召准率是衡量模型预测正类标签时的准确度的指标。它计算的是模型预测的正类中真正为正类的比例。换句话说&#xff0c;召准率表示在所有预测为正类的实例中&#xff0c;正确识别为正类的实例所占的比例。 其中…

07_注解与动态代理

注解 什么是注解 注解&#xff08;Annotation&#xff09;&#xff0c;就是 Java 代码里面的特殊标记&#xff0c;例如 Override、Test 等作用&#xff1a;让其他程序根据注解信息来决定怎么执行该程序注意&#xff1a;注解可以用在类上、构造器上、方法上、成员变量上、参数…

SQLserver通过字符串中间截取然后分组

当我们存的数据是json的时候可以全部取出在模糊查询但是有多个重复数据的时候就没办法准确的模糊出来这个时候我们就需要用的字符串截取 --创建函数create FUNCTION [dbo].[Fmax] (str varchar(50),start VARCHAR(50),length VARCHAR(50)) RETURNS varchar(max) AS BEGINDEC…

Spring MVC学习随笔-文件下载和上传(配置文件上传解析器multipartResolver)

学习视频&#xff1a;孙哥说SpringMVC&#xff1a;结合Thymeleaf&#xff0c;重塑你的MVC世界&#xff01;&#xff5c;前所未有的Web开发探索之旅 学习视频&#xff1a;【编程不良人】继spring之后快速入门springmvc,面对SpringMVC不用慌 六、SpringMVC 文件上传下载 6.1 文件…

【最通用版FPGA 实现 SPI 驱动】

最近研究了一下SPI协议的FPGA实现&#xff0c;发现网上很多大佬分享的方法都是针对某一特定的flash芯片或者某一传感器芯片来设计电路结构的。所以想根据SPI&#xff08;Serial Peripheral Interface&#xff09;的基本通讯协议实现一个通用版的SPI Master驱动。SPI在嵌入式领域…

同源策略与跨域

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 不论个人练习还是实际开…

【PUSDN】centos查看日志文件内容,包含某个关键字的前后5行日志内容,centos查看日志的几种方法

简述 centos查看日志的几种方法 centos查看日志文件内容&#xff0c;包含某个关键字的前后5行日志内容 前情提示 系统&#xff1a; 一说 部分截图、链接等因过期、更换域名、MD语法等可能不显示&#xff0c;可联系反馈&#xff08;备注好博文地址&#xff09;&#xff0c…

HR看好的字符函数和字符串处理函数!!!

本篇会加入个人的所谓‘鱼式疯言’❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言,而是理解过并总结出来通俗易懂的大白话,我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的&#xff0c;可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 前言 在本篇…

mybatis整合(手动添加jar包方式)

操作步骤 创建数据库 建立user表 放入数据 1、创建javaweb工程并添加Jar包 用到的jar包 junit 用于测试 mybatis框架&#xff1a;mybatis-3.5.9.jar mysql数据库&#xff1a;mysql-connector-java-8.0.28.jar 2、添加MyBatis核心配置文件 <?xml version"1.0"…

Leetcode刷题详解——乘积为正数的最长子数组长度

1. 题目链接&#xff1a;1567. 乘积为正数的最长子数组长度 2. 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你求出乘积为正数的最长子数组的长度。 一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。 请你返回乘积为正数的最长子数组长度。 示…

什么是结构化数据?哪些OCR软件可将图片文字转为结构化数据?

结构化数据是指按照一定的数据模型组织和存储的数据&#xff0c;具有明确的数据类型和数据关系&#xff0c;并且可通过计算机程序进行处理和分析。这种数据通常存储在定义明确的模式中&#xff0c;例如数据库&#xff0c;采用表格的形式存储&#xff0c;每个数据项都有特定的字…

Mover Creator 用户界面

1 “开始”对话框 首次打开 Mover Creator 时&#xff0c;出现的第一个页面是“开始”对话框&#xff0c;如下所示。从这里开始&#xff0c;用户可以选择开始设计飞机、武器或发动机。在上述每种情况下&#xff0c;用户都可以创建新模型或编辑现有模型。 1.1 新建模型 如果用…

Apache Doris 详细教程(二)

5、doris的查询语法 5.1、doris查询语法整体结构 SELECT [ALL | DISTINCT | DISTINCTROW ] -- 对查询字段的结果是否需要去重&#xff0c;还是全部保留等参数 select_expr [, select_expr ...] -- select的查询字段 [FROM table_references [PARTITION…

94基于matlab的蚁群算法 (ACO) 对付的图像边缘检测问题

基于matlab的蚁群算法 (ACO) 对付的图像边缘检测问题。提出基于蚁群算法的边缘检测方法是能够建立一个信息素矩阵表示提出了一种在图像每个像素位置的边缘信息根据大量的蚂蚁的运动有哪些派去在图像上移动。此外&#xff0c;运动这些蚂蚁是由图像的局部变化驱动强度值。数据可更…

U1编译概述

文章目录 基本概念定义一些概念 编译流程词法分析语法分析语义分析、生成中间代码中间代码 代码优化生成目标程序五个阶段中都需要做的两件事符号表管理出错处理 总结 其他概念多层中间表示和遍&#xff08;PASS&#xff09;三端模式课程概述 基本概念 定义 用高级语言编制的…

【Java 基础】18 I/O流

文章目录 1.基本概念2.字节流3.字符流4.标准输入输出5.最佳实践 I/O流&#xff08;Input/Output 流&#xff09;是计算机程序中不可或缺的一部分&#xff0c; 往大了说所有的操作都是IO。Java 提供了强大而灵活的 I/O 框架&#xff0c;支持各种数据的 读取和 写入操作。 1.基…

45 - 多线程性能优化常见问题

1、使用系统命令查看上下文切换 上下文切换常见的监测工具 1.1、Linux 命令行工具之 vmstat 命令 vmstat 是一款指定采样周期和次数的功能性监测工具&#xff0c;我们可以使用它监控进程上下文切换的情况。 vmstat 1 3 命令行代表每秒收集一次性能指标&#xff0c;总共获取 …

day5 两数之和为x

vector<int> twoSum(vector<int>& nums, int target) { std::unordered_map <int,int> map; for(int i 0; i < nums.size(); i) { // 遍历当前元素&#xff0c;并在map中寻找是否有匹配的key auto iter map.find(target - nums[i]); if(iter ! map…

【JavaSE】:String(二):深入String

深入String 一.字符串的存储二.字符串的不可变性三.字符串修改四.StringBuilder和StringBuffer 一.字符串的存储 我们知道双引号里的数据都是字符串常量&#xff0c;储存在字符串常量池当中。 例子 直接使用是比较地址。字符串常量池有一个特点&#xff1b;它会先检查该常量是否…

LLM-Intro to Large Language Models

LLM some LLM’s model and weight are not opened to user what is? Llama 270b model 2 files parameters file parameter or weight of neural networkparameter – 2bytes, float number code run parameters(inference) c or python, etcfor c, 500 lines code withou…