Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
@Slf4j
public class TestLambda {
//未使用和使用lambda表达式,对比
static void testRunLambdaContrast(){
// 不使用lambda表达式,创建一个线程
Runnable runnable1 = new Runnable() {
@Override
public void run() {
log.info("------ 不使用lambda表达式,创建一个线程 ------");
}
};
// 启动线程
new Thread(runnable1).start();
// 使用lambda表达式,创建一个线程
Runnable runnable2 = () -> log.info("------ 使用lambda表达式,创建一个线程 ------");
// 启动线程2
new Thread(runnable2).start();
}
public static void main(String[] args) {
//测试 未使用和使用lambda表达式,对比
testRunLambdaContrast();
}
}
总结:未使用和使用Lambda表达式都可以实现抽象方法,但是使用Lambda方法后会更加简洁;
// 借助java8中 消费型函数式接口,讲解基本用法
// 不使用lambda表达式实现
Consumer<String> consumer1 = new Consumer<String>() {
@Override
public void accept(String s) {
log.info("------ 不使用lambda表达式,实现Consumer1接口,消费数据:{} ------",s);
}
};
// 使用消费型接口1
consumer1.accept("kh96正在学习lambda表达式,标准写法");
// 使用lambda表达式,用法:带 1 个参数,没有返回值,标准写法
Consumer<String> consumer2 = (String s) -> {
log.info("------ 使用lambda表达式,实现Consumer2接口,消费数据:{} ------",s);
};
// 使用消费型接口2
consumer2.accept("kh96正在学习lambda表达式,标准写法");
//一个参数,可以省略类型声明
Consumer<String> consumer3 = (s) -> {
log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);
};
consumer3.accept("kh96正在学习lambda表达式,一个参数,可以省略类型声明");
//一个参数,可以省略小括号(没有参数,多个参数不能省略)
Consumer<String> consumer4 = s -> {
log.info("------ 使用lambda表达式,实现Consumer4接口,消费数据:{} ------",s);
};
consumer4.accept("kh96正在学习lambda表达式,一个参数,可以省略小括号");
//实现只有一条语句,可以省略大括号(有多条语句,不可以省略)
Consumer<String> consumer5 = s -> log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);
consumer5.accept("kh96正在学习lambda表达式,实现只有一条语句,可以省略大括号");
//实现有多条语句,不可以省略大括号
Consumer<String> consumer6 = s -> {
log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);
log.info("------ 使用lambda表达式,实现Consumer3接口,消费数据:{} ------",s);
};
consumer6.accept("kh96正在学习lambda表达式,实现有多条语句,不可以省略大括号");
// 借助Comparator接口,讲解多个参数
Comparator<Integer> comparator1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
// 未使用lambda表达式,用法:带多个参数,有返回值
log.info("------ 不使用lambda表达式,实现Comparator接口,比较12,23的大小:{} ------",comparator1.compare(12,23));// 小于 -1,大于 1,等于 0
//省略参数类型,但是不可以省略小括号,一条语句省略大括号,跟返回值无关(不用手动加return)
Comparator<Integer> comparator2 = (o1,o2) -> o1.compareTo(o2);
log.info("------ 使用lambda表达式,实现Comparator接口,比较23,12的大小:{} ------",comparator2.compare(23,12));// 大于 1
//多条语句不可以省略大括号,带返回值(需手动加return)
Comparator<Integer> comparator3 = (o1,o2) -> {
log.info("------ 比较原数值为:{},{}",o1,o2);
return o1.compareTo(o2);
};
log.info("------ 使用lambda表达式,实现Comparator接口,比较22,22的大小:{} ------",comparator3.compare(22,22));// 等于 0
//自定义方法,带有一个消费型接口参数,可以实现一个方法,处理不同的业务场景
static void useConsumer(Double salary,Consumer<Double> consumerDate){
consumerDate.accept(salary);
}
static void testLambdaConsumer(){
//场景,同一个接口,有多个实现,以前,必须要创建接口的多个实现类,现在使用lambda,把接口的实现交给调用方法传递
//实现1:Tom发了5000工资,去买手机,模拟接口的第一个实现
//以前,必须提供接口的实现类对象
useConsumer(5000.0,salary -> log.info("Tom,工资:{},5000买手机",salary));
//实现1:Tom发了10000工资,去买手机,买平板,模拟接口的第二个实现
//以前,必须提供接口的 两个 实现类对象
useConsumer(10000.0,slary -> {
log.info("JiMe工资:{},5000买手机",slary);
log.info("JiMe工资:{},4000买平板",slary);
});
}

//带一个供给型参数,可以实现同一个方法,处理实现同一个方法,处理不同的业务场景,给的数据不同,返回的结果不同
static String useSupplier(Double salary, Supplier<Double> supplierData){
//判断是否高薪的逻辑
if(salary > supplierData.get()){
return "高薪";
}
return "底薪";
}
static void testLambdaSupplier(){
//场景:不同的部门,针对高薪的判断条件不同,比如:学术部高于8000算高薪,教职部门高于5000算高薪
//以前的写法:根据不同的不同,增加if...else 判断,随着部门的增加,你分的判断会越来越复杂
log.info("--- 学术部:工资:{},是否高薪:{} ---",9000.0,useSupplier(9000.0,() -> 8000.0));
log.info("--- 学术部:工资:{},是否高薪:{} ---",7000.0,useSupplier(7000.0,() -> 8000.0));
log.info("--- 教职部:工资:{},是否高薪:{} ---",7000.0,useSupplier(7000.0,() -> 5000.0));
log.info("--- 教职部:工资:{},是否高薪:{} ---",4000.0,useSupplier(7000.0,() -> 5000.0));
}

//将判断条件交给调用方法
static List<String> userPredicate(List<String> nameList, Predicate<String> predicateData){
//定义要返回的姓名集合
List<String> returnNameList = new ArrayList();
//使用断言型接口,根据传过来的实现,返回不同的结果
nameList.forEach(name ->{
//调用断言型接口的test方法,进行挑选数据
if(predicateData.test(name)){
returnNameList.add(name);
}
});
//返回符合条件的集合数据
return returnNameList;
}
static void testLambdaPredicate(){
//使用场景
//已知姓名集合,根据不同的场景,筛选不同的姓名结果
List<String> nameList = Arrays.asList("Lilei","Hanmeinei","lisi","zhangsan","xiaolong","xiaohu");
//获取姓名集合中所有包含n的姓名集合,可以定义第一个方法,实现
//获取集合中包含i 或者a的姓名集合,可以定义第二个方法,实现
//随着规则的改变,实现的方法越来越多,去简化,所有的方法就是判断规则不同,其他都一样,可以使用断言型接口,优化
//获取姓名集合中所有包含n的姓名集合
List<String> nameList_n = userPredicate(nameList,name -> name.contains("n"));
log.info("姓名集合中所有包含n的姓名集合:{}",nameList_n);
//获取集合中包含i 或者a的姓名集合
List<String> nameList_i_a = userPredicate(nameList,name -> name.contains("i") || name.contains("a"));
log.info("获取集合中包含i 或者a的姓名集合:{}",nameList_i_a);
}

static void testLambdaFunction(){
Function<Integer,Double> function = num -> new Random().nextInt(num)*1.0;
log.info("--- 使用函数型接口,接收整数:{},返回随机浮点型结果:{} ---",96,function.apply(96));
}

// 自定义的函数式接口:带一个任意类型参数,返回String类型值
// 定义:凡是一个接口中,只有一个抽象方法,那这个接口就是函数式接口,可以别注解 //@FunctionalInterface修饰
@FunctionalInterface
public interface MyFunctionInterface<T> {
//函数式接口中的唯一抽象方法
String helloKh96(T t);
//可以增加默认方法,允许的
default void hiKH96(){
//默认方法
}
}
//有限流, 输出1,3,5,7,9 的平方
log.info("\n----- 输出1,3,5,7,9 的平方 -----");
Stream.of(1,3,5,7,9).forEach(num -> System.out.print(num * num + ";"));
测试结果:

//无限流:输出前18个奇数
log.info("\n ----- 输出前18个奇数 ------");
Stream.iterate(1,n -> n+2).limit(10).forEach(num -> System.out.print(num + ";"));
//无限流:输出10个随机数
log.info("\n ----- 输出前18个随机数 ------");
Stream.generate(() -> new Random().nextInt(100)).limit(10).forEach(num -> System.out.print(num+";"));
测试结果:

//基于数组
int[] nums = {66,99,44,11,22,55,77,88};
//通过Arrays工具类提供的stream 方法
int min = Arrays.stream(nums).min().getAsInt();
int max = Arrays.stream(nums).max().getAsInt();
log.info("\n ------ 数组最小值为 :{} --------",min);
log.info("\n ------ 数组最大值为 :{} --------",max);
测试结果:

//基于集合
List<String> nameList = Arrays.asList("Lilei","Hanmeinei","lisi","zhangsan","xiaolong","xiaohu");
//通过集合对象的stream方法
nameList.stream().map(name -> name.toLowerCase()).forEach(System.out::println);
测试结果:

//小说实体
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Story {
// 编号
private Integer id;
// 书名
private String name;
// 作者
private String author;
// 价格
private Double price;
// 章节
private Integer sections;
// 分类
private String category;
}
//小说工具类
public class StoryUtil {
public static List<Story> stories = new ArrayList<>();
static {
stories.add(Story.builder().id(101).name("斗破苍穹").author("zhangsan").price(109.9).sections(1202).category("玄幻").build());
stories.add(Story.builder().id(201).name("斗罗大陆").author("lisi").price(88.9).sections(999).category("科幻").build());
stories.add(Story.builder().id(301).name("凡人修仙传").author("wangwu").price(77.9).sections(1303).category("武侠").build());
stories.add(Story.builder().id(401).name("圣墟").author("zhuliu").price(121.9).sections(1404).category("玄幻").build());
stories.add(Story.builder().id(501).name("吞噬星空").author("sunqi").price(135.9).sections(996).category("历史").build());
stories.add(Story.builder().id(601).name("完美世界").author("zhaoba").price(66.9).sections(999).category("玄幻").build());
stories.add(Story.builder().id(701).name("大王饶命").author("qianjiu").price(135.9).sections(997).category("玄幻").build());
stories.add(Story.builder().id(801).name("大奉打更人").author("zhoushi").price(133.9).sections(1606).category("军事").build());
}
}
//筛选: filter,相当于数据库中的where条件
log.info("-------------- 筛选: filter ----------------");
//查看小说集合中,价格大于100块的所有小说
StoryUtil.stories.stream().filter(story -> story.getPrice() > 100).forEach(System.out::println);
//练习:查看小说集合中,所有章节数大于1000且作者中包含n的小说
log.info("\n------- 查看小说集合中,所有章节数大于1000且作者中包含n的小说 ---------");
StoryUtil.stories.stream().filter(story -> story.getSections() > 1000 && story.getAuthor().contains("n") ).forEach(System.out::println);
测试结果1:

测试结果2:

//截断: limit 相当于数据库的limit条数
log.info("\n---------- 截断: limit ---------");
//查询小说集合,所有价格大于100的前三本
StoryUtil.stories.stream().filter(story -> story.getPrice() >100).limit(3).forEach(System.out::println);
测试结果:

//跳过:skip,相当于数据库跳过数据条数
log.info("\n------------- 跳过:skip-----------------");
//查询小说集合,所有价格大于100的前三本,后的所有小说
log.info("\n------------- 查询小说集合,所有价格大于100的前三本,后的所有小说-----------------");
StoryUtil.stories.stream().filter(story -> story.getPrice() >100).skip(3).forEach(System.out::println);
测试结果:

//去重:distinct,相当于数据库中的去重,了解
log.info("\n------------- 去重:distinct,相当于数据库中的去重 -----------------");
Stream.of(22,33,55,11,66,33,55,11,55).distinct().forEach(System.out::println);
测试结果:

//已知姓名集合
List<String> nameList = Arrays.asList("Lilei","Hanmeinei","lisi","zhangsan","xiaolong","xiaohu");
//映射:map,可以将流中发的元素进行转换或这提取,会自动指定的规则作用到所有的元素上,并返回一个新的流
log.info("-------------- 映射: map ----------------");
//将姓名集合中,所有包含i的姓名,转换为大写并输出
//nameList.stream().filter(name -> name.contains("i")).map(name -> name.toUpperCase()).forEach(System.out::println);
nameList.stream().filter(name -> name.contains("i")).map(String::toUpperCase).forEach(System.out::println);
测试结果:

//将小说集合中,章节小于1000的作者转换为大写,输出作者
log.info("\n-------------- 将小说集合中,章节小于1000的作者转换为大写,输出作者 --------------");
//StoryUtil.stories.stream().filter(story -> story.getSections() < 1000).map(story -> story.getAuthor()).map(string -> string.toUpperCase()).forEach(System.out::println);
StoryUtil.stories.stream().filter(story -> story.getSections() < 1000).map(Story::getAuthor).map(string -> string.toUpperCase()).forEach(System.out::println);
测试结果:

//获取所有小说的书名长度
log.info("\n-------------- 获取所有小说的书名长度 --------------");
// StoryUtil.stories.stream().map(story -> story.getName().length()).forEach(System.out::println);
StoryUtil.stories.stream().mapToInt(story -> story.getName().length()).forEach(System.out::println);
测试结果:

//消费:peek, 将小说价格增加50元后,价格大于130的
log.info("\n-------------- 消费:peek, 将小说价格增加50元后,价格大于130的 --------------");
StoryUtil.stories.stream().peek(story -> story.setPrice(story.getPrice()+50)).filter(story -> story.getPrice()>130).forEach(System.out::println);
测试结果:

//排序:sorted ,给姓名排序
log.info("\n -------------- 排序:sorted ,给姓名排序 --------------");
nameList.stream().sorted().forEach(System.out::println);

//自定义排序,先按照价格排序,价格相同,按照章节排序
log.info("\n--------- 自定义排序,先按照价格排序,价格相同,按照章节排序 ---------");
StoryUtil.stories.stream().sorted((s1,s2)->{
int sortPrice = Double.compare(s1.getPrice(),s2.getPrice());
if(sortPrice == 0){
return Double.compare(s1.getSections(),s2.getSections());
}
return sortPrice;
}).forEach(System.out::println);
测试结果:

//全匹配:allMatch
log.info("------------ 全匹配:allMatch --------------");
//全匹配:allMatch ,所有的元素都要满足匹配条件,返回true,只要有一个不满足,就返回false;
//判断所有的小说价格都是大于60的
boolean allMatchFlag = StoryUtil.stories.stream().allMatch(story -> story.getPrice()> 60);
log.info("----- 是否所有的小说价格都是大于60:{} ------",allMatchFlag);
测试结果:

log.info("------------ 任意匹配:mnyMatch --------------");
//全任意匹配:mnyMatch ,所有的元素 只要有一个 满足匹配条件,返回false,全部不满足,就返回false;
//判断所有的小说 章节 有 小于990的
boolean mnyMatchFlag = StoryUtil.stories.stream().anyMatch(story -> story.getSections()> 990);
log.info("----- 是否所有的小说 章节 有 小于990的:{} ------",mnyMatchFlag);
测试结果:

log.info("------------ 全不匹配:noneMatch --------------");
//全不匹配:noneMatch ,所有的元素都 不 满足匹配条件,返回true,只要有一个满足,就返回false;
//判断存在武侠类小说
boolean noneMatchFlag = StoryUtil.stories.stream().noneMatch(story -> story.getCategory().equals("武侠"));
log.info("----- 是否 不 存在武侠类小说:{} ------",noneMatchFlag);
//判断存在 都市类小说
boolean noneMatchFlag2 = StoryUtil.stories.stream().noneMatch(story -> story.getCategory().equals("都市"));
log.info("----- 是否 不 存在都市类小说:{} ------",noneMatchFlag2);
测试结果:

log.info("------------ 统计:count --------------");
//统计:count,统计所有的元素满足条件的元素个数
//统计小说作者名字中包含a的数量
long count = StoryUtil.stories.stream().filter(story -> story.getAuthor().contains("a")).count();
log.info("------- 统计小说作者名字中包含a的数量:{} -------------",count);
测试结果:

log.info("------------ 最大值:max --------------");
//最大值:max,获取所有的元素满足条件的元素最大值
//获取所有小说中,最多的章节
Optional<Integer> maxSections = StoryUtil.stories.stream().map(story -> story.getSections()).max(Integer::compareTo);
log.info("------- 获取所有小说中,最多的章节:{} -------------",maxSections.get());
测试结果:

log.info("------------ 最小值:min --------------");
//最小值:min,获取所有的元素满足条件的元素最小值
//获取所有小说中,最低价格
Optional<Double> minPrice = StoryUtil.stories.stream().map(story -> story.getPrice()).min(Double::compareTo);
log.info("------- 获取所有小说中,最低价格:{} -------------",minPrice.get());
测试结果:

//获取所有小说中,分类为玄幻的小说,收集为新的小说结合
List<Story> storyList = StoryUtil.stories.stream().filter(story -> story.getCategory().equals("玄幻")).collect(Collectors.toList());
log.info("获取所有小说中,分类为玄幻的小说,收集为新的小说结合:{}",storyList);
测试结果:

//获取所有小说中,所有的分类集合(要去重)
Set<String> categorySet = StoryUtil.stories.stream().map(Story::getCategory).collect(Collectors.toSet());
log.info("------ 获取所有小说中,所有的分类集合(要去重):{} -----",categorySet);
测试结果:

//获取所有小说中,将小说编号作为key,小说名称作为value,收集map集合
Map<Integer,String> storyMap = StoryUtil.stories.stream().collect(Collectors.toMap(Story::getId,Story::getName));
log.info("------- 获取所有小说中,将小说编号作为key,小说名称作为value,收集map集合:{} ------",storyMap);
测试结果:

//获取所有小说中,根据小说的分类进行分组,同一个分类收集为新的集合
Map<String,List<Story>> storyCategoryMap = StoryUtil.stories.stream().collect(Collectors.groupingBy(Story::getCategory));
log.info("------- 取所有小说中,根据小说的分类进行分组,同一个分类收集为新的集合:{} ------",storyCategoryMap);
测试结果:

//求所有小说的平均价格
Double avgPrice = StoryUtil.stories.stream().map(Story::getPrice).collect(Collectors.averagingDouble(Double::doubleValue));
log.info("------- 求所有小说的平均价格:{} -------",avgPrice);
测试结果:

//一般遍历都是集合list或者map,如果需要遍历,不需要的中间操作,就可以直接调用forEach
StoryUtil.stories.forEach(story -> {
if(story.getCategory().equals("玄幻") && story.getAuthor().contains("a")){
log.info("满足条件的,小说:{}",story);
}
});
测试结果:

//map遍历,也支持,相对与以前,会更简洁
Map<Integer,String> storyMap = StoryUtil.stories.stream().collect(Collectors.toMap(Story::getId,Story::getName));
storyMap.forEach((k,v)->log.info("key:{},value:{}",k,v));
测试结果:

规约:一般时将流中的元素进行求和操作;
//一直数值结合
List<Integer> numList = Arrays.asList(11,22,33,44,5,66);
//常规写法
Optional<Integer> reduceSum1 = numList.stream().reduce((n, m) -> n + m);
log.info("--------- 所有的数值之和为:{} ----------",reduceSum1.get());
测试结果:

//简化写法
Optional<Integer> reduceSum2 = numList.stream().reduce(Integer::sum);
log.info("--------- 所有的数值之和为:{} ----------",reduceSum2.get());
测试结果:

//原理
Optional<Integer> reduceSum3 = numList.stream().reduce((x,y) ->{
log.info("x = {}",x);
x += y;
log.info("y = {}",y);
log.info("x_new = {}",y);
return x;
});
log.info("--------- 所有的数值之和为:{} ----------",reduceSum3.get());
测试结果:

//计算所有小说的章节总和
Optional<Integer> reduceSection = StoryUtil.stories.stream().map(Story::getSections).reduce(Integer::sum);
log.info("-------- 计算所有小说的章节总和:{} ----------",reduceSection.get());
测试结果:

// 当前时间的毫秒数
long currentMilli1 = Instant.now().toEpochMilli();
long currentMilli2 = System.currentTimeMillis(); // 只取毫秒,推荐
log.info("当前毫秒:{},{}", currentMilli1, currentMilli2);
//当前毫秒:1666168947407,1666168947407
// 当前日期,只有年月日,没有时间
LocalDate localDate1 = LocalDate.now();
log.info("当前日期:{}", localDate1);
log.info("当前日期:年-{},月-{},日-{}", localDate1.getYear(), localDate1.getMonthValue(), localDate1.getDayOfMonth());
//当前日期:2022-10-19
//当前日期:年-2022,月-10,日-19
// 指定日期
LocalDate localDate2 = LocalDate.of(2020, 8, 10);
log.info("指定日期:{}", localDate2);
//指定日期:2020-08-10
// 日期比较
log.info("日期是否相等:{}", localDate1.equals(localDate2));
log.info("日期之前:{}", localDate1.isBefore(localDate2));
log.info("日期之后:{}", localDate1.isAfter(localDate2));
//日期是否相等:false
//日期之前:false
//日期之后:true
// 当前时间,只有时间,没有年月日
log.info("当前时间:{}", LocalTime.now());
//当前时间:16:42:27.480
// 当前时间增加一个小时
log.info("当前时间增加1个小时:{}", LocalTime.now().plusHours(1));
//当前时间增加1个小时:17:42:27.480
// 判断当前年是否是闰年
log.info("当前年是否是闰年:{}", localDate2.isLeapYear());
//当前年是否是闰年:true
// 当前日期时间
log.info("当前日期时间:{}", LocalDateTime.now());
//当前日期时间:2022-10-19T16:42:27.480
// 日期格式化
log.info("当前日期格式化字符串:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
//当前日期格式化字符串:2022-10-19 16:42:27
// 判断2月多少天
log.info("2028年的2月份有多少天:{}", YearMonth.of(2028, Month.FEBRUARY).lengthOfMonth());
//2028年的2月份有多少天:29
// 判断是否是生日
LocalDate birthday = LocalDate.of(2000, 5, 7);
MonthDay birthdayMonthDay = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(LocalDate.now());
log.info("今天是生日吗?{}", currentMonthDay.equals(birthdayMonthDay));
//今天是生日吗?false
// 获取系统默认时区
log.info("默认时区:{}", ZoneId.systemDefault());
//默认时区:Asia/Shanghai
// 指定时区
log.info("指定时区:{}", ZoneId.of("America/Chicago"));
//指定时区:America/Chicago
// 时区对应时间
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Europe/Paris"));
//时区-Europe/Paris的时间:2022-10-19T10:42:27.508
// 带时区的时间
ZonedDateTime zonedDateTime = LocalDateTime.now().atZone(ZoneId.of("Asia/Shanghai"));
log.info("时区-Europe/Paris的时间:{} ", localDateTime);
log.info("时区-Asia/Shanghai的时间:{} ", zonedDateTime);
//时区-Asia/Shanghai的时间:2022-10-19T16:42:27.510+08:00[Asia/Shanghai]
/**
* Created On : 2022/10/19.
* <p>
* Author : zhukang
* <p>
* Description: 日期工具类
*/
public class DateUtil {
/**
* 显示年月日时分秒,例如 2022-05-07 09:09:09.
*/
public static final String DATE_PATTERN_ALL = "yyyy-MM-dd HH:mm:ss";
/**
* 仅显示年月日,例如 2022-05-07.
*/
public static final String DATE_PATTERN_YMD = "yyyy-MM-dd";
/**
* 仅显示时分秒,例如 09:09:09.
*/
public static final String DATE_PATTERN_HMS = "HH:mm:ss";
/**
* 显示年月日时分秒(无分隔符),例如 20220507090909.
*/
public static final String UNSIGNED_DATE_PATTERN_ALL = "yyyyMMddHHmmss";
/**
* 仅显示年月日(无分隔符),例如 20220507.
*/
public static final String UNSIGNED_DATE_PATTERN_YMD = "yyyyMMdd";
/**
* 星期日;
*/
public static final String WEEK_SUNDAY = "星期日";
/**
* 星期一;
*/
public static final String WEEK_MONDAY = "星期一";
/**
* 星期二;
*/
public static final String WEEK_TUESDAY = "星期二";
/**
* 星期三;
*/
public static final String WEEK_WEDNESDAY = "星期三";
/**
* 星期四;
*/
public static final String WEEK_THURSDAY = "星期四";
/**
* 星期五;
*/
public static final String WEEK_FRIDAY = "星期五";
/**
* 星期六;
*/
public static final String WEEK_SATURDAY = "星期六";
/**
* 获取日期时间字符串
*
* @param temporal 需要转化的日期时间
* @param pattern 时间格式
* @return String 日期时间字符串,例如 2022-05-07 17:25:05
*/
public static String format(TemporalAccessor temporal, String pattern) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return dateTimeFormatter.format(temporal);
}
/**
* 获取当前日期和时间字符串.
*
* @return String 日期时间字符串,例如 2022-05-07 09:09:09
*/
public static String formatLocalDateTime2String() {
return format(LocalDateTime.now(), DATE_PATTERN_ALL);
}
/**
* 获取当前日期和时间字符串,无符号
*
* @return String 日期时间字符串,例如 20220507090909
*/
public static String formatUnsignedLocalDateTime2String() {
return format(LocalDateTime.now(), UNSIGNED_DATE_PATTERN_ALL);
}
/**
* 获取当前日期字符串.
*
* @return String 日期字符串,例如2022-05-07
*/
public static String formatLocalDate2String() {
return format(LocalDate.now(), DATE_PATTERN_YMD);
}
/**
* 获取当前日期字符串,无符号
*
* @return String 日期字符串,例如2022-05-07
*/
public static String formatUnsignedLocalDate2String() {
return format(LocalDate.now(), UNSIGNED_DATE_PATTERN_YMD);
}
/**
* 日期时间字符串转换为日期时间(java.time.LocalDateTime)
*
* @param localDateTime 日期时间字符串
* @param pattern 日期时间格式 例如DATETIME_PATTERN
* @return LocalDateTime 日期时间
*/
public static LocalDateTime parseLocalDateTime(String localDateTime, String pattern) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return LocalDateTime.parse(localDateTime, dateTimeFormatter);
}
/**
* 日期字符串转换为日期(java.time.LocalDate)
*
* @param localDate 日期字符串
* @param pattern 日期格式 例如DATE_PATTERN
* @return LocalDate 日期
*/
public static LocalDate parseLocalDate(String localDate, String pattern) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
return LocalDate.parse(localDate, dateTimeFormatter);
}
/**
* 将Date转换为LocalDatetime,系统默认时区
*
* @param date 指定日期对象
* @return LocalDateTime 新的日期时间
*/
public static LocalDateTime parseDate2LocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
/**
* 将LocalDatetime转换为Date
*
* @return Date java.util.Date日期对象
*/
public static Date parseLocalDateTime2Date() {
return Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 获取当前时间字符串.
*
* @return String 时间字符串,例如 17:25:05
*/
public static String formatLocalTime2String() {
return format(LocalTime.now(), DATE_PATTERN_HMS);
}
/**
* 获取当前星期字符串.
*
* @return String 当前星期字符串,例如 星期二
*/
public static String getDayOfWeek() {
return format(LocalDate.now(), "E");
}
/**
* 获取指定日期是星期几
*
* @param localDate 日期
* @return String 星期几
*/
public static String getDayOfWeek(LocalDate localDate) {
String[] weekOfDays = {WEEK_MONDAY, WEEK_TUESDAY, WEEK_WEDNESDAY, WEEK_THURSDAY, WEEK_FRIDAY, WEEK_SATURDAY, WEEK_SUNDAY};
int dayOfWeek = localDate.getDayOfWeek().getValue() - 1;
return weekOfDays[dayOfWeek];
}
/**
* 获取指定日期时间加上指定时间单位的数量日期之后的日期时间.
*
* @param localDateTime 日期时间
* @param num 数量
* @param chronoUnit 日期时间单位
* @return LocalDateTime 新的日期时间
*/
public static LocalDateTime addDatetimeByUnit(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) {
return localDateTime.plus(num, chronoUnit);
}
/**
* 获取指定日期时间减去指定时间单位的数量日期之后的日期时间.
*
* @param localDateTime 日期时间
* @param num 数量
* @param chronoUnit 日期时间单位
* @return LocalDateTime 新的日期时间
*/
public static LocalDateTime subByDatetimeByUnit(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) {
return localDateTime.minus(num, chronoUnit);
}
/**
* 在指定日期时间的基础上增加月份和天数
*
* @param localDateTime 日期时间
* @param months 月份
* @param days 天数
* @return LocalDateTime 新的日期时间
*/
public static LocalDateTime addDatetimeMD(LocalDateTime localDateTime, int months, int days) {
return localDateTime.now()
.plus(months, ChronoUnit.MONTHS)
.plus(days, ChronoUnit.DAYS);
}
/**
* 在指定日期时间的基础上增加hour小时,minutes分钟和seconds秒
*
* @param hour 小时
* @param minutes 分钟
* @param seconds 秒
* @return LocalDateTime 新的日期时间
*/
public static LocalDateTime addDatetimeHms(int hour, int minutes, int seconds) {
return LocalDateTime.now()
.plus(hour, ChronoUnit.HOURS)
.plus(minutes, ChronoUnit.MINUTES)
.plus(seconds, ChronoUnit.SECONDS);
}
/**
* 在当前时间的基础上减少hour小时,minutes分钟和seconds秒
*
* @param hour 小时
* @param minutes 分钟
* @param seconds 秒
* @return LocalDateTime 新的日期时间
*/
public static LocalTime subDatetimeHms(int hour, int minutes, int seconds) {
return LocalTime.now()
.minus(hour, ChronoUnit.HOURS)
.minus(minutes, ChronoUnit.MINUTES)
.minus(seconds, ChronoUnit.SECONDS);
}
/**
* 判断给定日期字符串,是否当天
*
* @param date 给定日期字符串
* @return 是否当天
*/
public static boolean isToday(String date) {
return LocalDate.now().equals(LocalDate.parse(date));
}
/**
* 当前年份是否是闰年
*
* @return boolean 是否闰年标识
*/
public static boolean isLeapYear() {
return LocalDate.now().isLeapYear();
}
/**
* 当前指定年份是否是闰年
*
* @return boolean 是否闰年标识
*/
public static boolean isLeapYear(String date) {
return LocalDate.parse(date).isLeapYear();
}
/**
* 当前指定日期是否是生日
*
* @return boolean 是否闰年标识
*/
public static boolean isBirthday(String date) {
return MonthDay.from(LocalDate.parse(date)).equals(MonthDay.from(LocalDate.now()));
}
/**
* 根据日期时间单位,计算两个日期之间相隔年数或月数或天数
*
* @param start 开始日期
* @param end 结束日期
* @param chronoUnit 日期时间单位,(ChronoUnit.YEARS,ChronoUnit.MONTHS,ChronoUnit.WEEKS,ChronoUnit.DAYS)
* @return long 相隔年数或月数或天数
*/
public static long getYmdBetweenByUnit(LocalDate start, LocalDate end, ChronoUnit chronoUnit) {
return Math.abs(start.until(end, chronoUnit));
}
/**
* 根据指定时间单位,计算两个日期时间之间相隔日期时间
*
* @param start 开始日期时间
* @param end 结束日期时间
* @param chronoUnit 日期时间单位
* @return long 相隔日期时间
*/
public static long getTimeBetweenByUnit(LocalDateTime start, LocalDateTime end, ChronoUnit chronoUnit) {
return Math.abs(start.until(end, chronoUnit));
}
/**
* 获取本年第一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfYear() {
return getFirstDayOfYear(LocalDateTime.now());
}
/**
* 获取本年最后一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfYear() {
return getLastDayOfYear(LocalDateTime.now());
}
/**
* 获取指定日期当年第一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfYear(LocalDateTime localDateTime) {
return getFirstDayOfYear(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期当年最后一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfYear(LocalDateTime localDateTime) {
return getLastDayOfYear(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期当年第一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfYear(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withDayOfYear(1).withHour(0).withMinute(0).withSecond(0), pattern);
}
/**
* 获取指定日期当年最后一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfYear(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(TemporalAdjusters.lastDayOfYear()).withHour(23).withMinute(59).withSecond(59), pattern);
}
/**
* 获取本月第一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfMonth() {
return getFirstDayOfMonth(LocalDateTime.now());
}
/**
* 获取本月最后一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfMonth() {
return getLastDayOfMonth(LocalDateTime.now());
}
/**
* 获取指定日期当月第一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getFirstDayOfMonth(LocalDateTime localDateTime) {
return getFirstDayOfMonth(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期当月最后一天的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfMonth(LocalDateTime localDateTime) {
return getLastDayOfMonth(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期当月第一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfMonth(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0), pattern);
}
/**
* 获取指定日期当月最后一天的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfMonth(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59), pattern);
}
/**
* 获取本周第一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfWeek() {
return getFirstDayOfWeek(LocalDateTime.now());
}
/**
* 获取本周最后一天的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfWeek() {
return getLastDayOfWeek(LocalDateTime.now());
}
/**
* 获取指定日期当周第一天的日期字符串,这里第一天为周一
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfWeek(LocalDateTime localDateTime) {
return getFirstDayOfWeek(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期当周最后一天的日期字符串,这里最后一天为周日
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfWeek(LocalDateTime localDateTime) {
return getLastDayOfWeek(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期当周第一天的日期字符串,这里第一天为周一,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getFirstDayOfWeek(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(DayOfWeek.MONDAY).withHour(0).withMinute(0).withSecond(0), pattern);
}
/**
* 获取指定日期当周最后一天的日期字符串,这里最后一天为周日,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getLastDayOfWeek(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.with(DayOfWeek.SUNDAY).withHour(23).withMinute(59).withSecond(59), pattern);
}
/**
* 获取今天开始时间的日期字符串
*
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getStartTimeOfDayStr() {
return getStartTimeOfDay(LocalDateTime.now());
}
/**
* 获取今天结束时间的日期字符串
*
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getEndTimeOfDay() {
return getEndTimeOfDay(LocalDateTime.now());
}
/**
* 获取指定日期开始时间的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 00:00:00
*/
public static String getStartTimeOfDay(LocalDateTime localDateTime) {
return getStartTimeOfDay(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期结束时间的日期字符串
*
* @param localDateTime 指定日期时间
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getEndTimeOfDay(LocalDateTime localDateTime) {
return getEndTimeOfDay(localDateTime, DATE_PATTERN_ALL);
}
/**
* 获取指定日期开始时间的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd HH:mm:ss
*/
public static String getStartTimeOfDay(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withHour(0).withMinute(0).withSecond(0), pattern);
}
/**
* 获取指定日期结束时间的日期字符串,带日期格式化参数
*
* @param localDateTime 指定日期时间
* @param pattern 日期时间格式
* @return String 格式:yyyy-MM-dd 23:59:59
*/
public static String getEndTimeOfDay(LocalDateTime localDateTime, String pattern) {
return format(localDateTime.withHour(23).withMinute(59).withSecond(59), pattern);
}
}
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.
Java的Collections.unmodifiableList和Collections.unmodifiableMap在Ruby标准API中是否有等价物? 最佳答案 使用freeze应用程序接口(interface):Preventsfurthermodificationstoobj.ARuntimeErrorwillberaisedifmodificationisattempted.Thereisnowaytounfreezeafrozenobject.SeealsoObject#frozen?.Thismethodretur
在Java中,可以像这样从一个字符串创建一个IO流:Readerr=newStringReader("mytext");我希望能够在Ruby中做同样的事情,这样我就可以获取一个字符串并将其视为一个IO流。 最佳答案 r=StringIO.new("mytext")和here'sthedocumentation. 关于java-Java的StringReader的Ruby等价物是什么?,我们在StackOverflow上找到一个类似的问题: https://st