Java 8 特性

目录

1.Java8中Interface接口

2. Lambda 表达式

语法格式

3. 函数式接口 Functional Interface

示例

  示例1:排序

示例2:迭代

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

Predicate接口

 Function

 Comparator

4. Stream流

创建Stream

常用方法

Filter 过滤 

Sorted 排序

Map 映射

Match 匹配 

Count 计数

Collect 收集 

Parallel Streams 并行流 

函数式接口总结

05 日期时间

格式化

字符串转日期格式

日期计算

获取指定日期


1.Java8中Interface接口


        interface接口 的设计目的是面向接口编程,提高扩展性。
        Java8中,接口中除了抽象方法外,还可以定义default默认方法和static静态方法。
        default修饰的默认方法,属于实例方法,可以被实现类调用或重写。
调用:实现类必须implements接口,才能调用该接口的default默认方法。
重写:实现类implements不同接口时,接口中存在相同签名的方法(名称、参数、类型完全一致),则实现类必须重写该方法,明确方法定义;
        static修饰的静态方法,属于类的静态方法。但它不能被子类继承,只能用interface接口名称调用。


2. Lambda 表达式


        Lambda 表达式本质是一个匿名函数,用于把函数作为参数,传入方法中,实现函数式编程风格。   使用Lambda 表达式可以使代码变的更加简洁紧凑。


语法格式


        (parameters)-> expression 或 (parameters)->{ statements;}


3. 函数式接口 Functional Interface


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

示例


  示例1:排序

函数式接口Comparator
@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
}
使用Lambda实现函数式接口
// lambda表达式实现字符串数组排序
Arrays.sort(array, (x1,x2) -> {
    if (x1.length() != x2.length()) {
        return x1.length() - x2.length();
    } else {
        return x1.compareTo(x2);
    }
} );

示例2:迭代

使用Lambda迭代遍历集合
List<String> langList = Arrays.asList("Basic","QBasic","c","c++","PowerBuilder","Visual Basic");
		
langList.forEach((name)->{
    System.out.println(name);
});

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

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


Predicate接口


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

Predicate 断言型接口
package java.util.function;
import java.util.Objects;

@FunctionalInterface
public interface Predicate<T> {
    
    // 该方法是接受一个传入类型,返回一个布尔值.此方法应用于判断.
    boolean test(T t);

    // and方法与关系型运算符"&&"相似,两边都成立才返回true
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    
    // 与关系运算符"!"相似,对判断进行取反
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    
    //or方法与关系型运算符"||"相似,两边只要有一个成立就返回true
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    
   // 该方法接收一个Object对象,返回一个Predicate类型.此方法用于判断第一个test的方法与第二个test方法相同(equal).
   static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
	}
}

 示例:

// 案例数据
List<String> langList = Arrays.asList("Basic","QBasic","c","c++","PowerBuilder","go","Visual Basic","c#","java");

// 判断长度
int len = 5;
Predicate<String> predicateLen = (str)->{
    if(str.length() <= len) {
        return true;
    }
    return false;
};

// 判断前缀
String prefix = "c";
Predicate<String> predicatePrefix =(str)->{
    if(str.startsWith(prefix)) {
        return false;
    }
    return true;
};

// 逻辑与
Predicate<String> conditionAnd = predicateLen.and(predicatePrefix);

// 逻辑或
Predicate<String> conditionOr = predicateLen.or(predicatePrefix);

// 逻辑非
Predicate<String> conditionNot = predicateLen.negate();

// 遍历判断
langList.forEach((name)->{
    if(conditionAnd.test(name)) {
        System.out.println(name);
    }
});

 Function

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

package java.util.function;
 
import java.util.Objects;
 
@FunctionalInterface
public interface Function<T, R> {
    
    // 将Function对象应用到输入的参数上,然后返回计算结果。
    R apply(T t);
    
    // 将两个Function整合,并返回一个能够执行两个Function对象功能的Function对象
    // 作用等同于:apply(before.apply(v))
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    
    // 将两个Function整合,并返回一个能够执行两个Function对象功能的Function对象
    // 作用等同于:before.apply(apply())
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
}

案例:

// 案例数据
List<String> langList = Arrays.asList("Basic", "QBasic", "c", "c++", "PowerBuilder", "go", "Visual Basic", "c#","java");

// 转成大写
Function<String, String> funcToUpper = (name) -> {
    return name.toUpperCase();
};

// 添加标记符号
Function<String, String> funcAddTag = (name) -> {
    return "[" + name + "]";
};

// 合并操作
Function<String, String> func = funcToUpper.andThen(funcAddTag);

// 遍历并处理
langList.forEach((name) -> {
    name = func.apply(name);
    System.out.println(name);
});

 Comparator

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

// 案例数据
List<String> langList = Arrays.asList("Basic", "QBasic","HTML", "c", "c++", "PowerBuilder", "go", "Visual Basic", "c#","java");

// 按照ASCII码比较
Comparator<String> comparator1 = (s1, s2) -> {
    return s1.compareTo(s2);
};

// 按照长度比较
Comparator<String> comparator2 = (s1, s2) -> {
    return s1.length() - s2.length();
};

// 先比较长度,再比较ASCII码
Comparator<String> comparator3 = comparator2.thenComparing(comparator1);

// 在comparator3的基础上,反转条件
Comparator<String> comparator4 = comparator2.reversed();

// 按照指定Comparator,进行排序
langList.sort(comparator2);

4. Stream流

        java.util.Stream 表示能应用在一组元素上一次执行的操作序列。
        Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,可以连续完成多个操作。

创建Stream

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

List<String> list = Arrays.asList("Basic", "QBasic","HTML", "c", "c++", "PowerBuilder", "go", "Visual Basic", "c#",
				"java");
Stream<String> stream = list.stream();

常用方法

/**
boolean allMatch(Predicate<? super T> predicate)

/**
* 此流任意元素是否有与提供的predicate匹配。
*/
boolean anyMatch(Predicate<? super T> predicate);

/**
* 返回一个 Stream的构建器。
*/
public static<T> Builder<T> builder();

/**
* 使用 Collector对此流的元素进行归纳
*/
<R, A> R collect(Collector<? super T, A, R> collector);

/**
 * 返回此流中的元素数。
*/
long count();

/**
* 返回由该流的不同元素(根据 Object.equals(Object) )组成的流。
*/
Stream<T> distinct();

/**
 * 遍历
*/
void forEach(Consumer<? super T> action);

/**
* 用于获取指定数量的流,截短长度不能超过 maxSize 。
*/
Stream<T> limit(long maxSize);

/**
* 用于映射每个元素到对应的结果
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);

/**
* 根据提供的 Comparator进行排序。
*/
Stream<T> sorted(Comparator<? super T> comparator);

/**
* 在丢弃流的第n个元素后,返回由该流剩余元素组成的流。
*/
Stream<T> skip(long n);

/**
* 返回一个包含此流的元素的数组。
*/
Object[] toArray();

/**
* 使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。
*/
<A> A[] toArray(IntFunction<A[]> generator);

/**
* 合并流
*/
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)

Filter 过滤 

         

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

示例:

List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
	    
// 返回符合条件的stream流
// 计算流符合条件的stream流的数量
long count  = strings.stream().filter(s -> "abc".equals(s)).count();

System.out.println(count);

Sorted 排序

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

示例:

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

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);

Match 匹配 

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

示例:

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

// 整体匹配
boolean isMatch1 = strings.stream().allMatch((s) -> s.length() == 3);
System.out.println(isMatch1); // false

// 局部匹配
boolean isMatch2 = strings.stream().anyMatch((s) -> s.length() == 3);
System.out.println(isMatch2); // true

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);

Collect 收集 

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

将Stream中的元素,收集至新集合
Collectors.toList()
Collectors.toSet()
Collectors.toMap()
示例:过滤Stream中的元素,并将过滤结果收集到一个新的集合(List、Set、Map)

// 将过滤结果,收集至List集合,默认为ArrayList
List<String> resultList = langList.stream()
                                .filter(s->s.toUpperCase().contains("B"))
                                .collect(Collectors.toList());
System.out.println(resultList);

// 将过滤结果,收集至LinkedList集合
LinkedList<String> resultLinkedList = langList.stream()
                                                .filter(s->s.toUpperCase().contains("B"))
                                                .collect(Collectors.toCollection(LinkedList::new));
System.out.println(resultLinkedList);

// 将过滤结果,收集至Set集合,默认为HashSet
Set<String> resultSet = langList.stream()
                                .filter(s->s.toUpperCase().contains("B"))
                                .collect(Collectors.toSet());

// 将过滤结果,收集至Map集合,默认为HashMap
Map<String,Integer> resultMap = langList.stream()
                                        .filter(s->s.toUpperCase().contains("B"))
                                        .collect(Collectors.toMap(s->s, s->s.length()));
System.out.println(resultMap);

        将Stream中的元素,映射后,收集至新集合 Collectors.mapping()
示例:对Stream中的每个元素进行映射,并将映射结果收集到一个新的集合(List)

// 将字符串集合中的每个字符串,映射转换为Integer
List<String> numberStrings = Arrays.asList("4344","6641","3432","6432","6423","9423");
List<Integer> numberList = numberStrings.stream()
    								.collect(Collectors.mapping(s->Integer.parseInt(s), Collectors.toList()));
System.out.println(numberList);

        将Stream中的元素,分组后,收集至Map集合Collectors.groupingBy()
示例:对Stream中的每个元素进行分组统计,并将统计结果收集到一个新的集合(Map) 

// 按照字符数统计
Map<Integer,List<String>> resultMap1 = langList.stream()
    										.collect(Collectors.groupingBy(s->s.length()));
System.out.println(resultMap1);
		
// 按照首字母统计
Map<Character,List<String>> resultMap2 = langList.stream()
    										.collect(Collectors.groupingBy(s->s.toLowerCase().charAt(0)));
System.out.println(resultMap2);

将Stream中的元素,按照判断规则,统计分区后,收集至Map集合Collectors.partitioningBy() 

示例:

List<Integer> number = Arrays.asList(1, 2, 5, 4);

IntSummaryStatistics statistics = number.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : "+statistics.getMax());
System.out.println("列表中最小的数 : "+statistics.getMin());
System.out.println("平均数 : "+statistics.getAverage());
System.out.println("所有数之和 : "+statistics.getSum());

Parallel Streams 并行流 

        Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。
示例:排序
准备示例数据

int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
    UUID uuid = UUID.randomUUID();
    values.add(uuid.toString());
}

串行排序:

long t0 = System.nanoTime();
long count = values.stream().sorted().count();
System.out.println(count);

long t1 = System.nanoTime();

long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("串行排序,耗时共计: %d 毫秒", millis));

串行排序,耗时共计591毫秒

并行排序:

long t0 = System.nanoTime();

long count = values.parallelStream().sorted().count();
System.out.println(count);

long t1 = System.nanoTime();

long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("并行排序,耗时共计: %d 毫秒", millis));

并行排序,耗时共计283毫秒

函数式接口总结

        1.Predicate、Function、Consumer、Comparator
        2.通过链式编程,使得它可以方便地对数据进行链式处理。
        3.方法参数都是函数式接口类型。
        4.一个 Stream 只能操作一次,操作完就关闭了,继续使用这个 Stream 会报错。
        5.Stream 不保存数据,不改变数据源。

05 日期时间

        Java 8在java.time 包下包含一个全新的日期和时间API。
        ●LocalDateTime //日期+时间 format: yyyy-MM-ddTHH:mm:ss.SSS
        ●LocalDate //日期 format: yyyy-MM-dd
        ●LocalTime //时间 format: HH:mm:ss

格式化

//Format yyyy-MM-dd
LocalDate date = LocalDate.now();
System.out.println(String.format("Date format : %s", date));

//Format HH:mm:ss
LocalTime time = LocalTime.now().withNano(0);
System.out.println(String.format("Time format : %s", time));

//Format yyyy-MM-dd HH:mm:ss
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateTimeStr = dateTime.format(dateTimeFormatter);
System.out.println(String.format("DateTime Format : %s", dateTimeStr));

字符串转日期格式

LocalDate date1 = LocalDate.of(2021, 1, 26);
LocalDate date2 = LocalDate.parse("2021-01-26");
System.out.println(date1);
System.out.println(date2);

LocalDateTime dateTime1 = LocalDateTime.of(2021, 1, 26, 12, 12, 22);
LocalDateTime dateTime2 = LocalDateTime.parse("2021-01-26T12:12:22");
System.out.println(dateTime1);
System.out.println(dateTime2);

LocalTime time1 = LocalTime.of(12, 12, 22);
LocalTime time2 = LocalTime.parse("12:12:22");
System.out.println(time1);
System.out.println(time2);

日期计算

// 计算一周后的日期
LocalDate localDate = LocalDate.now();

// 方法1
LocalDate after1 = localDate.plus(1, ChronoUnit.WEEKS);
System.out.println("一周后日期:" + after1);

// 方法2
LocalDate after2 = localDate.plusWeeks(1);
System.out.println("一周后日期:" + after2);

// 计算两个日期间隔多少天,计算间隔多少年,多少月
LocalDate date1 = LocalDate.parse("2021-02-26");
LocalDate date2 = LocalDate.parse("2021-12-23");
Period period = Period.between(date1, date2);
System.out.println("date1 到 date2 相隔:" + period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天");

// 计算两个日期间隔多少天
long day = date2.toEpochDay() - date1.toEpochDay();
System.out.println(date2 + "和" + date2 + "相差" + day + "天");

获取指定日期

LocalDate today = LocalDate.now();
		
// 获取当前月第一天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("当前月第一天:" + firstDayOfThisMonth);

// 获取本月最后一天
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("本月最后一天:" + lastDayOfThisMonth);

// 获取下一天:
LocalDate nextDay = lastDayOfThisMonth.plusDays(1);
System.out.println("下一天(次月第一天):" + nextDay);

// 获取当年最后一天
LocalDate lastday = today.with(TemporalAdjusters.lastDayOfYear());
System.out.println("当前月第一天:" + lastday);

// 获取当年最后一个周日
LocalDate lastMondayOfThisYear = lastday.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));
System.out.println("当年最后一个周日:" + lastMondayOfThisYear);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿究◎小飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值