JAVA8新特性

JAVA8新特性学习入门案例

1.接口的默认方法

允许给接口添加一个非抽象的方法实现,只需要使用default关键字即可,这个特征叫做扩展方法。

public interface InterfaceDemo {
    double sum(int a);
    
    default double sqrt(int a){
        return Math.sqrt(a);
    }
}

实现InterfaceDemo接口时,只需要实现一个sum方法,默认方法sqrt在子类上直接使用。

public class InterfaceTest {
    public static void main(String[] args) {
        InterfaceDemo interfaceDemo = new InterfaceDemo(){
            @Override
            public double sum(int a){
                return sqrt(a * 100);
            }
        };
        System.out.println(interfaceDemo.sum(100));
        System.out.println(interfaceDemo.sqrt(16));
    }
}
2.构造引用

使用 :: 关键字来传递方法或者构造者引用。

格式:
//  对象名 :: 方法名
// 类名 :: 静态方法名

创建一个类

public class Person {
    String firstName;
    String lastName;

    Person(){
        
    }

    Person(String firstName,String lastName){
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

接下来指定一个用来创建Person对象的对象接口。

public interface PersonFactory<P extends Person> {
    P creat(String firstName, String lastName);
}

这里我们将他们关联起来,而不是实现一个完整的工厂。

public class PersonTest {
    public static void main(String[] args) {
        PersonFactory personFactory = Person::new;
        Person person = personFactory.creat("sqq", "sxm");
        System.out.println(person.firstName);
        System.out.println(person.lastName);
    }
}
3.lambda表达式

这边我要是使用JAVA8中Predicate(断定和假设的意思)的函数式接口,可以被应用于lambda表达式和方法引用。他包含了一个接口方法和三个默认方法以及一个静态方法。

这边我们使用一个test方法,它是一个写判断逻辑的代码。

public class LambdaDemo1 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        System.out.println(exec(list, new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer%2 == 0;
            }
        }));

    }

    private static List<Integer> exec(List<Integer> list, Predicate<Integer> predicate){
       List<Integer> list1 = new ArrayList<>();
        for (Integer i : list){
            if(predicate.test(i)){
                list1.add(i);
            }
        }
       return list1;
    }
}

接下来把main方法中的变成lambda表达式。把整个输出替换掉。

  System.out.println(exec(list, i -> i%2 == 0)); 

(1)我们一般使用主要是使用他自己的里面的一个方法stream()。

public class LambdaDemo2 {
    public static void main(String[] args) {
        List<Integer> list= Arrays.asList(1,2,3,4,5);
        //1.转成流
        Stream<Integer> stream = list.stream();
        //过滤方法 只要2的倍数
        Stream<Integer> stream1 = stream.filter(i -> i % 2 == 0);
        //各个元素 *2 映射
        Stream<Integer> stream2 = stream1.map(i -> i * 2);
        //收集结果
        List<Integer> collect = stream2.collect(Collectors.toList());
        System.out.println(collect);
    }
}

可以一句写完。

 System.out.println(list.stream().filter(i -> i%2 == 0).map(i -> i*2).collect(Collectors.toList()));

(2)各种方法例子集合

public class LambdaDemo3 {
    public static void main(String[] args) throws IOException {
        ArrayList<String[]> list = new ArrayList<>();
        list.add(new String[]{"张三","王五"});
        list.add(new String[]{"张三","王五2"});

        // 1. flatmap 遍历
        List<String> collect = list.stream().flatMap(strings -> stream(strings)).collect(toList());
        System.out.println(collect);
        // 2. 遍历 foeEach
        collect.forEach( s -> System.out.println(s));

        //3.map的遍历 接受一个双参数的。。
        HashMap<String,String> map = new HashMap<>();
        map.put("1","宋");
        map.put("2","李");
        map.forEach((key,value) -> System.out.println(key+"------"+value));

        //求个数  是list的size
        System.out.println(list.stream().count());
        //去重服  ,  张三重复
        System.out.println(collect.stream().distinct().collect(Collectors.toList()));

        //数组流
        int [] array = {3,22,5,3,5,67,3,134,};
        List<Integer> integers = asList(2, 3, 4, 6, 34, 21, 3121, 3, 5);
        //最大值
        System.out.println(Arrays.stream(array).max());

        // 文件读取流  ,  在遍历
        Files.lines(Paths.get("1.txt")).forEach(i -> System.out.println(i));

        //使用生产者的接口来随机生成几个整数
        Random random = new Random();
        Stream.generate(() -> random.nextInt(100)).limit(5).forEach( s -> System.out.println(s));
        // :: 关键字方法调用
        Stream.generate(() -> random.nextInt(100)).limit(5).forEach( System.out::println);

        //格式:
        //  对象:: 方法名
        // 类型 :: 静态方法名
        Arrays.stream(array).filter(i -> i%2 == 0);
        // 类名:: 静态方法名
        System.out.println(integers.stream().filter(LambdaDemo3::aa).collect(toList()));
    }

    public static boolean aa(Integer x){
        //代码多
        return x % 2 == 0;
    }
}
4.访问局部变量

使用lambda表达式中访问外层局部变量,可以直接访问被final修饰的的外层局部变量,或者实例的字段以及静态变量。

public class LambdaDemo2 {
    
    interface Convert<T1,T2> {
        void convert(int from);
    }
    public static void main(String[] args) {
    final int num = 1;
    Convert<Integer,String> s = (param) -> System.out.println(String.valueOf(param + num));
    s.convert(2); // 输出结果是3
    }
}

lambda表达式的局部变量可以不用final,但是必须不可被后面的代码修改(即隐形的具有fina的语义),如果改的话,会报错,需要添加final。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CRRKsP8e-1574220811019)(C:\Users\M S I\AppData\Roaming\Typora\typora-user-images\1574213074651.png)]

public class LambdaDemo2 {

    interface Convert<T1,T2> {
        void convert(int from);
    }
    public static void main(String[] args) {
        int num = 1;  // 前面默认有final
    Convert<Integer,String> s = (param) -> System.out.println(String.valueOf(param + num));
    s.convert(2); // 输出结果是3
     //   num = 5;    注释掉要修改的隐式常量就好了。
    }
}
5.访问对象子弹与静态变量

和本地变量不同的是,lambda内部对于实例的字段以及静态变量是即可读有可写,该行为和匿名对象是一致的。

public class LambdaDemo3 {
    static int outerStaticNum;
    int outerNum;
    void testScopes(){
        LambdaDemo2.Convert<Integer,String> stringConverter1 = (param) ->{
            outerNum = 23;
            System.out.println(outerNum);
        };
    }

    LambdaDemo2.Convert<Integer,String> stringConvert2 = (param) -> {
        outerStaticNum = 72;
        System.out.println(outerStaticNum);
    };
}
6.Date API

JAVA8中在包java.time下包含了一组全新的时间日期API。

Clock 时钟

Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以取代System.currentTImeMillis() 来获取当前的微妙数,某一个特定的时间也可以使用instant类来表示,instant类也可以用来创建老的java.util.Date对象。

 	 Clock clock = Clock.systemDefaultZone();
     long millis = clock.millis();
     System.out.println(millis); // 1574216290018
      //  可以代替  Date
     Instant instant = clock.instant();
     Date date = Date.from(instant);
     System.out.println(date); // Wed Nov 20 10:18:10 CST 2019
Timezones时区

在新API中时区使用Zoneld来表示,时区可以很方便的使用静态方法of来获取到。时区定义了带UTS时间的时间差,在instant时间点对象到本地日期对象之间转换的时候是极其重要的。

  System.out.println(ZoneId.getAvailableZoneIds());
         // [Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/GMT+8, Africa/Nairobi, 			America/Marigot, Asia/Aqtau, Pacific/Kwajalein,
        // Asia/Chungking, America/Managua, America/Indiana/Petersburg, Asia/Yerevan, 	  Europe/Brussels, 
        // GMT, Europe/Warsaw, America/Chicago, Asia/Kashgar, Chile/Continental, 		Pacific/Yap, CET, Etc/GMT-1, 
        // Etc/GMT-0, Europe/Jersey, America/Tegucigalpa, Etc/GMT-5, Europe/Istanbul, 	  America/Eirunepe, Etc/GMT-4,
        // America/Miquelon, Etc/GMT-3, Europe/Luxembourg, Etc/GMT-2, Etc/GMT-9, 		America/Argentina/Catamarca, Etc/GMT  等等]
        ZoneId zone1 = ZoneId.of("Europe/Berlin");
        System.out.println(zone1.getRules());
        //   ZoneRules[currentStandardOffset=+01:00]
LocalTime 本地时间

localTime定义了一个没有时区信息的时间, 例如 晚上10点 , 或者 17:30:15。 下面的例子使用前面代码创建的时区创建了两个本地时间,之后比较时间并以小时和分钟为单位计算两个时间的时间差:

LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
LocalDate yesterday = tomorrow.minusDays(2);

LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4);
DayOfWeek dayOfWeek = independenceDay.getDayOfWeek();

System.out.println(dayOfWeek);    // FRIDAY

时间这种东西,现在看了,不一定用得上,什么时候用,到时看看就行。新特性,主要还是lambda表达式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值