Java8特性

目录

一、Interface接口

二、Lambda表达式

三、函数式接口 Functional Interface

3.1  内置函数式接口 (Built-in Functional Interfaces)

3.1.1  Predicate接口

3.1.2  Function

3.1.3  Comparator

四、Stream流

4.1  创建Stream

 4.2  常用方法

4.2.1  Filter过滤

4.2.2  Sorted排序

4.2.3  Map映射

4.2.4  Match匹配

4.2.5  Count计数

4.2.6  Collect收集

4.2.7  Statistics 统计

4.2.8  Parallel Streams 并行流

五、日期时间

5.1  格式化

5.2  字符串转日期格式

5.3  日期计算

5.4  获取指定日期


一、Interface接口

Java8中,接口中除了抽象方法外,还可以定义default默认方法和static静态方法。

  • default修饰的默认方法,属于实例方法,可以被实现类调用或重写。
    • 调用:实现类必须implements接口,才能调用该接口的default默认方法。
    • 重写:实现类implements不同接口时,接口中存在相同签名的方法(名称、参数、类型完全一致),则实现类必须重写该方法,明确方法定义。
  • static修饰的静态方法,属于类的静态方法。但它不能被子类继承,只能用interface接口名称调用。

二、Lambda表达式

Lambda 表达式本质是一个匿名函数,用于把函数作为参数,传入方法中,实现函数式编程风格。

使用Lambda 表达式可以使代码变的更加简洁紧凑。

语法格式:(parameters)-> expression 或 (parameters)->{ statements;}

三、函数式接口 Functional Interface

只有一个抽象方法的接口(可以定义多个非抽象方法)。可以使用@FunctionalInterface接口定义,强化语义规范。
 作用:基于函数式接口,可以使用Lambda表达式进行实现,实现函数式编程。

示例1:排序

List<String> list=Arrays.asList("ab","hdhdh","a","cd","java");
//Lambda表达式实现Comparator接口
list.sort((o1,o2)->{
	if(o1.length()==o2.length()) {
		return o1.compareTo(o2);
	}
	return o1.length()-o2.length();
});
System.out.println(list);

示例2:迭代

public class Demo01 {
	public static void main(String[] args) {
		List<String> list=Arrays.asList("ab","hdhdh","a","cd","java");		
		//使用Lambda迭代遍历集合
		list.forEach((s)->{
			System.out.println(s);
		});
	}

}

3.1  内置函数式接口 (Built-in Functional Interfaces)

在 Java 8 中专门有一个包放函数式接口java.util.function,该包下的所有接口都有 @FunctionalInterface 注解,提供函数式编程方式。

3.1.1  Predicate接口

Predicate接口是只有一个参数的返回布尔类型值的断言型接口。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与and,或or,非negate)。

public class Demo02 {
	public static void main(String[] args) {
		List<String> list=Arrays.asList("ab#","hdh$h","a%","cd","java");
		//判断长度不等于5
		Predicate<String> predicate1=(s)->{
			return s.length()!=5;
		};
		//判断是否全为字母
		Predicate<String> predicate2=(s)->{
			for(int i=0;i<s.length();i++) {
				if(!Character.isLetter(s.charAt(i))) {
					return false;
				}
			}
			return true;
		};
		//逻辑与(and方法与关系型运算符"&&"相似,两边都成立才返回true)
		Predicate<String> predicate3=predicate1.and(predicate2);
        //逻辑或(or方法与关系型运算符"||"相似,两边只要有一个成立就返回true)
		Predicate<String> predicate4=predicate1.or(predicate2);
        //逻辑非(与关系运算符"!"相似,对判断进行取反)
		Predicate<String> predicate5=predicate4.negate();

		list.forEach((s)->{
			System.out.println(s+"是否符合条件:"+predicate5.test(s));
		});
				
	}

}
3.1.2  Function

Function 接口接受一个参数并生成结果。默认方法可用于将多个函数链接在一起(compose, andThen)。

public class Demo03 {
	public static void main(String[] args) {
		//Function接口
		List<String> list=Arrays.asList("ab#","hdh$h","a%","cd","java");
//				list.stream()//切换成stream流
//				.map((s)->{   //map映射操作
//					//return s.toUpperCase();	
//					return s.length();
//				}).forEach((s)->{
//					System.out.println(s);
//				});
		//转成大写
		Function<String, String> fun1=(s)->{
			return s.toUpperCase();
		};
		//添加尖括号
		Function<String, String> fun2=(s)->{
			return String.format("<%s>", s);
		};
		//组合
		Function<String, String> fun3=fun1.andThen(fun2);
		Function<String, String> fun4=fun1.compose(fun2);

		list.stream().map(fun3).forEach((s)->{
			System.out.println(s);
		});
	}
}
3.1.3  Comparator

比较器接口,用于比较指定元素值的大小。Java8版本中,添加了多个新的default方法,用于比较器合并、反转等操作。

//Comparator接口
public class Demo04 {
	public static void main(String[] args) {
		List<String> list=Arrays.asList("ab#","hdhhhh","a%","cd","java");
		//按内容比较
		Comparator<String> comp1=(x,y)->{
			return x.compareTo(y);
		};
		//按长度比较
		Comparator<String> comp2=(x,y)->{
			return x.length()-y.length();
		};
		//先比较内容,再比较长度
		Comparator<String> comp3=comp1.thenComparing(comp2);
		//按内容降序(反转条件)
		Comparator<String> comp4=comp1.reversed();
		//按照指定Comparator,进行排序
		list.sort(comp4);
		
		System.out.println(list);

	}

}

四、Stream流

java.util.Stream 表示能应用在一组元素上一次执行的操作序列。

Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,可以连续完成多个操作。

4.1  创建Stream

Stream 的创建需要指定一个数据源。

List<String> list=Arrays.asList("稻香","夜曲","东风破","青花瓷");
Stream<String> stream = list.stream();

 4.2  常用方法

4.2.1  Filter过滤

过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作。所以过滤后的结果,可以继续进行其它Stream操作(例如forEach,forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作)。

		//数组
		String[] array= {"稻香","夜曲","东风破","青花瓷","青花瓷","听妈妈的话","夜曲","稻香","稻香"};
		Stream<String> arrayStream=Arrays.stream(array);
				
		//先过滤再统计歌曲名称长度为3的数量
		long count=arrayStream.filter((music)->{
			return music.length()==3;
		}).count();
		System.out.println(count);
4.2.2  Sorted排序

排序是一个中间操作,返回的是排序好后的Stream。(不影响原数据)

List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
	    
// 排序并遍历
strings.stream()
        .sorted()
        .forEach(System.out::println);
4.2.3  Map映射

映射是一个中间操作,会将元素根据指定的 Function 接口来依次将元素转成另外的对象。

List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");

// 转换字符串为大写,降序后,输出
strings.stream()
    .map((item)->{return item.toUpperCase();})
    .sorted((s1,s2)->{return s2.compareTo(s1);})
    .forEach(System.out::println);
4.2.4  Match匹配

Stream提供了多种匹配操作,允许检测指定的Predicate是否匹配整个Stream。所有的匹配操作都是最终操作 ,并返回一个 boolean 类型的值。

		List<String> list=Arrays.asList("稻香","夜曲","东风破","青花瓷");
	
		//是否有任意元素匹配
		boolean isContains1=list.stream().anyMatch((music)->{
			return music.length()==2;
		});
		System.out.println(isContains1);
		//是否所有元素匹配
		boolean isContains2=list.stream().allMatch((music)->{
			return music.length()==2;
		});
		System.out.println(isContains2);
		//没有元素匹配
		boolean isContains3=list.stream().noneMatch((music)->{
			return music.length()==1;
		});
		System.out.println(isContains3);
4.2.5  Count计数

计数是一个最终操作,返回Stream中元素的个数,返回值类型是 long。

List<String> strings = Arrays.asList("abc", "deft", "gkh", "abc");
		
// 统计“a”开头的元素个数
long count = strings.stream().filter((s)->s.startsWith("a")).count();
System.out.println(count);
4.2.6  Collect收集

收集是一个最终操作,返回Stream中元素集合,返回值类型是集合(List、Set、Map)或字符串。

将Stream中的元素,收集至新集合:

  • Collectors.toList()
  • Collectors.toSet()
  • Collectors.toMap()
        String[] array= {"稻香","夜曲","东风破","青花瓷","青花瓷","听妈妈的话","夜曲","稻香","稻香"};
		Stream<String> arrayStream=Arrays.stream(array);
        //去重并收集,将结果收集至List集合,默认为ArrayList
		List<String> musicList=arrayStream.distinct()
		.collect(Collectors.toList());
		System.out.println(musicList);
		
        // 将结果收集至Set集合,默认为HashSet
		Set<String> musicSet=Arrays.stream(array).collect(Collectors.toSet());
		System.out.println(musicSet);
		
		//distinct去重后,stream中的元素收集成一个LinkedList集合(有序,需要去重)
		LinkedList<String> musicLinkedList=Arrays.stream(array)
				.distinct()
				.collect(Collectors.toCollection(LinkedList::new));
		System.out.println(musicLinkedList);
		//将stream中的元素收集成一个LinkedHashSet集合(值唯一,有序)
		LinkedHashSet<String> musicLinkedHashSet=Arrays.stream(array)
				.collect(Collectors.toCollection(LinkedHashSet::new));
		System.out.println(musicLinkedHashSet);
		
		//将stream流中的元素收集为一个map集合,默认为HashMap
		Map<String,Integer> musicMap1=Arrays.stream(array).distinct()
		.collect(Collectors.toMap(
				(music)->{return music;},
				(music)->{return music.length();}));
		System.out.println(musicMap1);
		
		Map<String,Integer> musicMap2=Arrays.stream(array).distinct()
				.collect(Collectors.toMap(
						music->music,
						music->music.length()));
				System.out.println(musicMap2);

将Stream中的元素,映射后,收集至新集合:

  • Collectors.mapping() 
List<String> strList=Arrays.asList("12","23","34","45","56","67");
//收集元素的同时进行mapping映射操作
//将字符串集合中的每个字符串,映射转换为Integer,并将每个数乘10
List<Integer> intList=strList.stream().collect(Collectors
		.mapping(
				s->Integer.parseInt(s)*10,
				Collectors.toList()));
System.out.println(intList);

 将Stream中的元素,分组后,收集至Map集合:

  • Collectors.groupingBy()
List<String> list=Arrays.asList("曹操","刘备","曹植","张飞","夏侯惇","曹丕","刘能","夏侯渊");
//分组
Map<Character, List<String>> resultMap=list
		.stream()
		.collect(Collectors
				.groupingBy(name->name.charAt(0)));
				
System.out.println(resultMap);

将Stream中的元素,按照判断规则,统计分区后,收集至Map集合:

  • Collectors.partitioningBy()
List<String> list=Arrays.asList("曹操","刘备","曹植","张飞","夏侯惇","曹丕","刘能","夏侯渊");

//分区
Map<Boolean,List<String>> resultPart=list
		.stream()
		.collect(Collectors.partitioningBy(name->name.length()==2));
System.out.println(resultPart);
4.2.7  Statistics 统计

统计是一个最终操作,返回Stream中元素的各类统计信息,返回值类型是 XXXConsumer。

List<Integer> list=Arrays.asList(2,6,8,10);
Stream<Integer> stream= list.stream();
IntStream intStream=stream.mapToInt(x->x);
IntSummaryStatistics statistics= intStream.summaryStatistics();
System.out.println("最大值:"+statistics.getMax());
System.out.println("最小值:"+statistics.getMin());
System.out.println("平均值:"+statistics.getAverage());
System.out.println("累加和:"+statistics.getSum());
4.2.8  Parallel Streams 并行流

Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。

int max=1000000;
List<String> values=new ArrayList<String>(max);
for(int i=0;i<max;i++) {
	UUID uuid=UUID.randomUUID();
		values.add(uuid.toString());
}
	
long start=System.currentTimeMillis();
//串行流
//long count=values.stream().sorted().count();
//并行流
long count=values.parallelStream().sorted().count();

long end=System.currentTimeMillis();
System.out.println(end-start);

注意:

1、一个 Stream 只能操作一次,操作完就关闭了,继续使用这个 Stream 会报错。

2、Stream 不保存数据,不改变数据源。

五、日期时间

5.1  格式化

//yyyy-MM-dd
LocalDate date=LocalDate.now();
System.out.println(String.format("当前日期:%s", date));
//HH:mm:ss
LocalTime time=LocalTime.now().withNano(0);
System.out.println(String.format("当前时间:%s", time));
			
LocalDateTime dateTime=LocalDateTime.now();
System.out.println(String.format("日期时间:%s", dateTime));
		
//yyyy-MM-dd HH:mm:ss
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateTimeStr = dateTime.format(dateTimeFormatter);
System.out.println(String.format("DateTime Format : %s", dateTimeStr));
		

5.2  字符串转日期格式

//类型转换
//字符串=》LocalDate
String strDate="2023-08-17";
date=LocalDate.parse(strDate);
System.out.println(String.format("指定日期:%s", date));
//整数值-》LocalDate
date=LocalDate.of(2023, 8, 15);
System.out.println(String.format("指定日期:%s", date));
	
LocalTime time1 = LocalTime.of(12, 12, 22);
LocalTime time2 = LocalTime.parse("12:12:22");
System.out.println(time1);
System.out.println(time2);
		
LocalDateTime dateTime1 = LocalDateTime.of(2023, 1, 26, 12, 12, 22);
LocalDateTime dateTime2 = LocalDateTime.parse("2023-01-26T12:12:22");
System.out.println(dateTime1);
System.out.println(dateTime2);

5.3  日期计算

LocalDate now=LocalDate.now();
System.out.println(now.plus(10,ChronoUnit.DAYS));
System.out.println(now.plus(-10,ChronoUnit.DAYS));
		
LocalDate date1=LocalDate.parse("2000-08-18");
LocalDate date2=LocalDate.parse("2021-07-20");
		
Period result=Period.between(date1, date2);
System.out.printf("间隔%d年,间隔%d月,间隔%d天",result.getYears(),result.getMonths(),result.getDays());
		
long days=date1.toEpochDay()-date2.toEpochDay();
System.out.println("间隔:"+days+"天");

5.4  获取指定日期

LocalDate today=LocalDate.now();
LocalDate firstDayOfMonth=today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("当月第一天:"+firstDayOfMonth);
		
		
System.out.println("当月最后一天:"+today.with(TemporalAdjusters.lastDayOfMonth()));

System.out.println("下个月第一天:"+today.with(TemporalAdjusters.lastDayOfMonth()).plusDays(1));
		
System.out.println("当月最后一个星期一:"+today.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY)));

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值