Java8新特性学习

目录

Interface

 functional interface 函数式接口

Lambda表达式

Stream流

Optional

Date-Time API


Interface

Java8中Interface新增了支持静态方法和默认方法(default)。

静态方法,调用方式为接口名.方法名。

增加这两种方法的原因:

假设我们存在一个很久之前写好的接口,后面因为业务原因需要修改接口。

java8之前,在一个接口中添加一个抽象方法,那所有的接口实现类都需要去实现这个方法,否则会编译出错。就算某些实现类不需要这个方法,也需要实现一个空方法。如果该接口的实现类特别多,改动会非常大。

接口实现默认方法就是为了解决这个问题,只要在一个接口中添加了默认方法,所有的实现类就自动继承,不需要改动任何实现类,也不会影响业务。


接口静态方法和默认方法类似,只是接口静态方法不可以被接口接口实现类重写。

 functional interface 函数式接口

指的是只能有一个抽象方法的接口,一般配合Lambda表达式一起使用。

Lambda表达式

函数式接口可以使用Lambda表达式来使用。传统的一些接口也支持lambda表达式写法,比如Runnable接口、Comparator接口、Listener 接口:

// Runnable 接口
new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("The runable now is using!");
            }
}).start();
//用lambda
new Thread(() -> System.out.println("It's a lambda function!")).start();

// Comparator 接口
List<Integer> strings = Arrays.asList(1, 2, 3);

Collections.sort(strings, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
    return o1 - o2;}
});

//Lambda
Collections.sort(strings, (Integer o1, Integer o2) -> o1 - o2);
//分解开
Comparator<Integer> comparator = (Integer o1, Integer o2) -> o1 - o2;
Collections.sort(strings, comparator);
// Listener 接口
JButton button = new JButton();
button.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
   e.getItem();
}

我们也可以写一些自定义的接口来使用lambda表达式,接口的创建要符合函数式接口的规则。

@FunctionalInterface
public interface LambdaInterface {
 void f();
}
//使用
public class LambdaClass {
    public static void forEg() {
        lambdaInterfaceDemo(()-> System.out.println("自定义函数式接口"));
    }
    //函数式接口参数
    static void lambdaInterfaceDemo(LambdaInterface i){
        i.f();
    }
}

当一个方法的返回值是functional-interface类型时,Java8支持使用::进行调用。

public class LambdaClassSuper {
    // 返回的类型为functional-interface
    LambdaInterface sf(){
        return null;
    }
}

class LambdaClass extends LambdaClassSuper {
    public static LambdaInterface staticF() {
        return null;
    }
    public LambdaInterface f() {
        return null;
    }
    void show() {
        //1.调用静态函数,返回类型必须是functional-interface
        LambdaInterface t = LambdaClass::staticF;

        //2.实例方法调用
        LambdaClass lambdaClass = new LambdaClass();
        LambdaInterface lambdaInterface = lambdaClass::f;

        //3.超类上的方法调用
        LambdaInterface superf = super::sf;

        //4. 构造方法调用
        LambdaInterface tt = LambdaClassSuper::new;
    }
}

Stream流

并行流

default Stream<E> parallelStream()

串行流

default Stream<E> stream()

常用API

/**
* 返回一个串行流
*/
default Stream<E> stream()

/**
* 返回一个并行流
*/
default Stream<E> parallelStream()

/**
* 返回T的流
*/
public static<T> Stream<T> of(T t)

/**
* 返回其元素是指定值的顺序流。
*/
public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}


/**
* 过滤,返回由与给定predicate匹配的该流的元素组成的流
*/
Stream<T> filter(Predicate<? super T> predicate);

/**
* 此流的所有元素是否与提供的predicate匹配。
*/
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元素后,返回由该流的 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)

使用

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

    //forEach遍历->打印元素
    strings.stream().forEach(System.out::println);

    //limit 获取到1个元素的stream
    Stream<String> limit = strings.stream().limit(1);
    //toArray 比如我们想看这个limitStream里面是什么,比如转换成String[],比如循环
    String[] array = limit.toArray(String[]::new);

    //map 对每个元素进行操作返回新流
    Stream<String> map = strings.stream().map(s -> s + "22");

    //sorted 排序并打印
    strings.stream().sorted().forEach(System.out::println);

    //Collectors collect 把abc放入容器中
    List<String> collect = strings.stream().filter(string -> "abc".equals(string)).collect(Collectors.toList());
    //把list转为string,各元素用,号隔开
    String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));

    //对数组的统计,比如用
    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());

    //concat 合并流
    List<String> strings2 = Arrays.asList("xyz", "jqx");
    Stream.concat(strings2.stream(),strings.stream()).count();

    //注意 一个Stream只能操作一次,不能断开,否则会报错。
    Stream stream = strings.stream();
    //第一次使用
    stream.limit(2);
    //第二次使用
    stream.forEach(System.out::println);
    //报错 java.lang.IllegalStateException: stream has already been operated upon or closed

    //但是可以这样, 连续使用
    stream.limit(2).forEach(System.out::println);
}

map和faltMap

map将每个元素映射为一个新的元素,返回一个新的流,flatMap将每个元素生成一个新的流,然后合并成一个更大的流。map操作关注单个元素的映射,flatMap关于元素的拆分合并。

mapflatMap 都是将一个函数应用于集合中的每个元素,但不同的是map返回一个新的集合,flatMap是将每个元素都映射为一个集合,最后再将这个集合展平。

在实际应用场景中,如果map返回的是数组,那么最后得到的是一个二维数组,使用flatMap就是为了将这个二维数组展平变成一个一维数组。

List<String> listArrays = Arrays.asList("apple", "banana", "orange");  
List<String> upperList = listArrays.stream().map(String::toUpperCase).collect(Collectors.toList());


// 将一个字符串流中的每个字符串拆分成单词:
List<String> listArrays = Arrays.asList("helloworld", "welcometoJava");  
List<String> wordList = listArrays.stream().flatMap(str -> Arrays.stream(str.split(""))).collect(Collectors.toList());  

Optional

为了解决空指针而推出。

常用API:
isPresent(): 如果 Optional 对象包含一个非空值,则返回 true,否则返回 false。

Optional<String> optionalString = Optional.of("Hello, world!");  
boolean isPresent = optionalString.isPresent();  
System.out.println(isPresent); // 输出 true  

ifPresent(Consumer<? super T> action): 如果 Optional 对象包含一个非空值,则对该值执行给定的操作。

Optional<String> optionalString = Optional.of("Hello, world!");  
optionalString.ifPresent(s -> System.out.println(s));  
// 输出 Hello, world!  

orElse(T other): 如果 Optional 对象包含一个非空值,则返回该值,否则返回给定的默认值。

Optional<String> optionalString = Optional.of("Hello, world!");  
String value = optionalString.orElse("Default value");  
System.out.println(value); // 输出 Hello, world!  

orElseGet(Supplier<? extends T> other): 如果 Optional 对象包含一个非空值,则返回该值,否则返回由给定的 Supplier 生成的值。

Optional<String> optionalString = Optional.of("Hello, world!");  
String value = optionalString.orElseGet(() -> "Default value");  
System.out.println(value); // 输出 Hello, world!  

orElseThrow(Supplier<? extends X> exceptionSupplier): 如果 Optional 对象包含一个非空值,则返回该值,否则抛出由给定的 Supplier 生成的异常。

Optional<String> optionalString = Optional.of("Hello, world!");  
String value = optionalString.orElseThrow(() -> new NoSuchElementException("Value is empty"));  
System.out.println(value); // 输出 Hello, world!  

map(Function<? super T,? extends U> mapper): 如果 Optional 对象包含一个非空值,则对该值应用给定的映射函数,并返回一个包含映射结果的 Optional 对象。否则返回一个空的 Optional 对象。

Optional<String> optionalString = Optional.of("Hello, world!");  
Optional<String> upperCaseOptional = optionalString.map(String::toUpperCase);  
String upperCaseValue = upperCaseOptional.orElse("No value present");  
System.out.println(upperCaseValue); // 输出 HELLO, WORLD!  

flatMap(Function<? super T,? extends Optional<? extends U>> mapper): 如果 Optional 对象包含一个非空值,则对该值应用给定的映射函数,并返回映射函数生成的 Optional 对象。否则返回一个空的 Optional 对象。

Optional<String> optionalString = Optional.of("Hello, world!");  
Optional<String> flatMappedOptional = optionalString.flatMap(s -> Optional.of(s.toUpperCase()));  
String flatMappedValue = flatMappedOptional.orElse("No value present");  
System.out.println(flatMappedValue); // 输出 HELLO, WORLD!  

filter(Predicate<? super T> predicate): 如果 Optional 对象包含一个非空值并且该值满足给定的谓词,则返回包含该值的 Optional 对象。否则返回一个空的 Optional 对象。

Optional<String> optionalString = Optional.of("Hello, world!");  
Optional<String> filteredOptional = optionalString.filter(s -> s.length() > 5);  
String filteredValue = filteredOptional.orElse("No value present");  
System.out.println(filteredValue); // 输出 Hello, world! 

Date-Time API

Java 8 引入了一些新的日期和时间 API,其中包括:


LocalDate:表示不带时区的日期,例如 2022-01-01。
LocalTime:表示不带时区的时间,例如 12:30:00。
LocalDateTime:表示不带时区的日期和时间,例如 2022-01-01T12:30:00。
ZonedDateTime:表示带时区的日期和时间,例如 2022-01-01T12:30:00+08:00[Asia/Shanghai]。
DateTimeFormatter:用于格式化和解析日期和时间的模式字符串。

获取当前日期:
LocalDate currentDate = LocalDate.now();  
System.out.println(currentDate);  
获取当前时间:
LocalTime currentTime = LocalTime.now();  
System.out.println(currentTime);  
获取当前日期和时间:
LocalDateTime currentDateTime = LocalDateTime.now();  
System.out.println(currentDateTime);  
创建一个特定的日期和时间:
LocalDateTime specificDateTime = LocalDateTime.of(2022, 1, 1, 12, 30, 0);  
System.out.println(specificDateTime);  
格式化日期和时间:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");  
String formattedDateTime = currentDateTime.format(formatter);  
System.out.println(formattedDateTime);  
将字符串解析为日期和时间:
String dateTimeString = "2022-01-01 12:30:00";  
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");  
LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString, formatter);  
System.out.println(parsedDateTime);  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值