Java8 新特性

Java8引入了StreamAPI,提供了数据处理的新方式,支持内部迭代和延迟执行。Stream操作包括中间操作(如filter、distinct、limit)和终端操作(如forEach、reduce、collect)。Lambda表达式简化了函数式编程,允许将函数作为参数传递。此外,接口增加了默认方法和静态方法,增强了灵活性。
摘要由CSDN通过智能技术生成

Java8 新特性

Stream 流

概念

流是数据通道,用于操作处理(查找、过滤、筛选)数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算”。

  • Stream 不会存储数据,也不会改变源对象;采用的内部迭代操作,会返回一个持有结果的新Stream;
  • Stream 操作是延迟执行(Lazy),直到调用终止操作才会开始执行计算;

特点

  • 流对数据源进行各种操作完成后,只能遍历一遍
  • 流对数据源的迭代操作与使用迭代器的显示迭代不同,而是采用内部迭代操作;
List<String> title = Arrays.asList("Java8", "In", "Action");
Stream<String> s = title.stream();
s.forEach(System.out::println);
s.forEach(System.out::println);

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
	at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
	at com.hp.blog.test.interfacetest.InterfaceTest.main(InterfaceTest.java:25)

操作

分为中间操作终端操作

  • 中间操作
    当数据源中的数据上了流水线后,这个过程对数据进行的所有操作都称为“中间操作”。
    中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。

  • 终端操作
    当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行“终端操作”。
    终端操作将返回一个执行结果,这就是你想要的数据。

代码示例

  • 中间操作
public static void main(String[] args) {
    List<Integer> intList = Arrays.asList(1,2,1,3,3,4,5,6,7,8,9,10);
    List<String> strList = Arrays.asList("aaa","bbb","ccc","ddd","eee");

    // filter() --> 接收Lambda,从流中排除某些元素
    intList.stream()
        .filter(e -> e >= 2)
        .forEach(e -> System.out.print(e + "\t"));
    // distinct() --> 筛选通过流产生元素的 hashcode() 和 equal() 去除重复元素
    intList.stream()
        .distinct()
        .forEach(e -> System.out.print(e + "\t"));
    // limit(long maxSize) --> 截断流,使其元素不超过给定数量
    intList.stream()
        .limit(4)
        .forEach(e -> System.out.print(e + "\t"));
    // skip(long n) --> 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
    intList.stream()
        .skip(5)
        .forEach(e -> System.out.print(e + "\t"));

    // map() --> 接收Lambda,将流中元素转换成其他类型或提取数据
    strList.stream()
        .map(String::toUpperCase)
        .forEach(e -> System.out.print(e + "\t"));
    // mapToInt、mapToDouble、mapToLong
    intList.stream()
        .mapToDouble(Integer::doubleValue)
        .forEach(e -> System.out.print(e + "\t"));
    // flatMap() --> 接收一个函数作为参数,将流中的每个值都转成另一个流,然后把所有流连接成一个流???
    strList.stream()
        .flatMap(testStreamAPI2::filterCharacter);
    
    // sorted() --> 自然排序
    intList.stream()
        .sorted()
        .forEach(e -> System.out.print(e + "\t"));
    // sorted(Comparator com) --> 定制排序
    intList.stream()
        .sorted((x,y) -> y.compareTo(x))
        .forEach(e -> System.out.print(e + "\t"));
}
  • 终止操作
public static void main(String[] args) {
    List<Integer> intList = Arrays.asList(1,2,1,3,3,4,5,6,7,8,9,10);
    
    // forEach(Consumer c) --> 内部迭代
	// min(Comparator c) --> 返回流中最小值
    Integer min = intList.stream()
        .filter(a -> a > 1)
        .min(Integer::compareTo)
        .get();
    System.out.println(min);
    // max(Comparator c) --> 返回流中的最大值
    Integer max = intList.stream()
        .filter(a -> a <= 3)
        .max((Integer a, Integer b) -> a.compareTo(b))
        .get();
    System.out.println(max);

    // findFirst --> 返回第一个元素
    Integer first = intList.stream()
        .findFirst()
        .get();
    System.out.println(first);

    // findAny --> 返回当前流中的任意元素
    Integer any = intList.stream()
        .findAny()
        .get();
    System.out.println(any);

    // count() --> 返回流中元素的总个数
    Long count = intList.stream()
        .filter(a -> a > 1)
        .count();
    System.out.println(count);
    
    // reduce() --> 归约,将流中元素反复结合起来,得到一个值
    Integer sum = intList.stream()
        .reduce(0, (x, y) -> x + y);
    System.out.println(sum);

    // collect(Collector c) --> 收集,将流转化为其他形式,接收一个Collectors接口的实现,用于Stream中元素做汇总的方法
    // Collectors接口中方法的实现决定了如何对流执行收集操作,静态方法toList(),toSet(),toCollection()
    Set<Integer> collect = intList.stream()
        .filter(e -> e > 4)
        .collect(Collectors.toSet());
    Iterator<Integer> iterator = collect.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
}
public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        personList.add(new Person("Owen", 9500, 25, "male", "New York"));
        personList.add(new Person("Alisa", 7900, 26, "female", "New York"));
    
        List<String> salaryNameList = personList.stream().filter(x -> x.getSalary() > 8000).map(Person::getName).collect(Collectors.toList());
        System.out.println("薪资是否大于8000的员工姓名集合:" + salaryNameList);

        Map<?, Person> salaryToMap = personList.stream().filter(x -> x.getSalary() > 8000).collect(Collectors.toMap(Person::getName, person -> person));
        System.out.println("员工薪资大于8000的员工信息:" + salaryToMap);

        Map<Boolean, List<Person>> salaryPart = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
        System.out.println("员工按薪资是否大于8000分两区域:" + salaryPart);

        Map<String, List<Person>> sexGroup = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        System.out.println("员工按性别分组:" + sexGroup);

        Map<String, List<Person>> areaGroup = personList.stream().collect(Collectors.groupingBy(Person::getArea));
        System.out.println("员工按区域分组:" + areaGroup);

        Map<String, Map<String, List<Person>>> sexAreaGroup = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
        System.out.println("员工按性别分组后再按区域分组:" + sexAreaGroup);
    }

public class Person {
    private String name;  // 姓名
    private int salary; // 薪资
    private int age; // 年龄
    private String sex; //性别
    private String area;  // 地区
}

函数式接口

函数式接口:指接口只有一个抽象函数,接口的默认方法和静态方法不会破坏函数式接口定义,接口通过 @FunctionalInterface 注解标识,这样的接口可以隐式转化为 Lambda 表达式;

@FunctionalInterface
public interface Functional {
    void method();
}

@FunctionalInterface
public interface FunctionalDefaultMethods {
    void method();
 
    default void defaultMethod() {            
    }        
}

Lambda 表达式

Lambda 表达式(也称闭包)它允许开发者将函数当做方法参数传递给某个方法,或者函数本身作为数据处理操作,使得代码更加简洁。Lambda表达式是一个可传递的代码块,可以被一次或多次调用执行。

Lambda表达式 ( 参数 ) -> { 方法体 }

其中 () 用来描述参数列表,{} 用来描述方法体,-> Lambda运算符,读作goes to。

Arrays.asList("a", "b", "c").forEach(e -> System.out.println(e));

// 显式指定参数类型
Arrays.asList("a", "b", "d").forEach((String e) -> System.out.println(e));

// Lambda 执行更复杂的语句块,用 {} 包括起来,类似Java中函数体
Arrays.asList("a", "b", "d").forEach(e -> {
    System.out.println(e);
    System.out.print(e + "\t");
})
    
// Lambda 表达式可以引用类成员和局部变量,并将这些变量隐式转换为 final 修饰)
// Error: java: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
String separator = ",";
separator = ".";
Arrays.asList("a", "b", "d").forEach(
    (String e) -> System.out.print(e + separator));

// Lambda表达式有返回值,当方法体只有一行代码时,return语句可省略,返回值类型有Java编辑器推理得出
Arrays.asList("a", "b", "c").forEach(e1, e2 -> e1.compartTo(e2));

Arrays.asList("a", "b", "c").forEach(e1, e2 -> {
    int result = e1.compartTo(e2);
    return result;
});

接口的默认和静态方法

默认方法

  • 默认方法允许开发者在接口提供默认方法实现(方法体),默认方法允许在不打破现有继承体系的基础上改进接口,默认方法可以使用实现类对象直接调用,或在实现类中对其进行覆盖重写后调用;
  • 主要作用:1.接口升级,可以避免改变其他实现类。2.函数拼接
  • 格式:public default 返回值方法名() {}

静态方法

  • 因为静态方法不可以实例化,在接口中也是一样的,不需要实例化,直接使用,节省内存空间。
  • 格式:public static 返回值 方法名() {}
  • 注意:接口中静态方法和类中静态方法一样,只能通过接口.静态方法名的方式调用
public interface DefaultMethodInterface {
    default String defaultTest() {
        return "Default Implementation";
    }

    static String staticTest() {
        return "Static Test";
    }
}

public class DefaultMethodInterfaceImpl implements DefaultMethodInterface {}

public class OverridableImpl implements DefaultMethodInterface {
    @Override
    public String defaultTest() {
        return "Override Implementation";
    }
}
public class InterfaceTest {
    public static void main(String[] args) {
		// 默认方法
        DefaultMethodInterfaceImpl defaulable = new DefaultMethodInterfaceImpl();
        System.out.println(defaulable.defaultTest());

        OverridableImpl overridable = new OverridableImpl();
        System.out.println(overridable.defaultTest());
		// 静态方法
        System.out.println(DefaultMethodInterface.staticTest());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值