接口实现
第一种方式:创建实现类 ,用实现类进行接口的实现
第二种方式:通过匿名内部类进行进行实现
基于匿名内部类实现的方式,特点:
内部类:
1 代码比较复杂,比较繁琐
2 匿名内部类,类,执行过程中,需要进行编译,------》花费时间比较长
3 需要编译,形成class文件,在硬盘上占用空间
4匿名内部类 实现接口,接口中可以有多个抽象方法
lambda表达式:
1 代码简化,不形成类,不需要编译,不需要占用硬盘空间(不生成.class文件)
2 lambda表达式,只能有一个抽象方法
lambda表达式:
格式:
实现的接口中方法的形参 指向 方法体(方法逻辑)
() -> {}
1.2.1 对接口抽象方法实现使用对lambda表达式简化
格式:()->{}
1 参数部分的简化:
如果方法是无参方法,()不能省略
如果方法是有参数的方法,参数数据类型可以省略
注意:如果参数有多个,数据类型同时省略
注意:如果参数有一个,数据类型可以省略,并且在数据类型省略的同时,()可以省略
2 方法的方法体简化
有返回值的方法,无返回值方法
无返回值方法:如果方法中只有一句方法的逻辑代码,{}可以省略
有返回值的方法:如果方法只有一句代码,省略return关键词,
在return省略的前提下,{}可以省略的
-
无参数列表,无返回值
public interface Cat { void eat(); } --------------> public class Test1 { public static void main(String[] args) { Cat cat = () -> { System.out.println("我是eat实现"); }; cat.eat(); Cat cat1 = () -> System.out.println("我是eat实现"); cat1.eat(); }
Cat cat1 = () -> System.out.println("我是eat实现");
cat1.eat(); -
参数列表,无返回值
Person p = (String name, int age) -> { System.out.println("名字是:"+name + "年龄是:" + age); }; p.call("张三", 12); Person p1 = (name, age) ->{ System.out.println("名字是:"+name + "年龄是:" + age); }; p1.call("张三", 12); //最终写法 Person p2 = (name, age) -> System.out.println("名字是:"+name + "年龄是:" + age); p2.call("张三", 12);如果有多个参数,可以省略参数数据类型;
如果方法体中只有一句代码,可以省略{}; -
有参数列表,有返回值
shape shape1 = (String b)->{ return "面积为" +b; }; String area = shape1.area("12平方公里"); System.out.println(area); shape shape2 = b -> { return "面积为" +b; }; shape2.area("12平方公里"); //最终写法 shape shape3 = b -> "面积为"+b; shape2.area("12平方公里");如果只有一个参数,可以省略参数数据类型,并且可以省略参数列表括号;
如果方法体只有一句代码,可以省略{},如果含有return,也可以省略retren
- 静态方法的引用
在lambda表达式中,进行方法引用,逻辑实现中的方法的参数和接口中要实现的方法的参数保持一致
对静态方法的引用:
格式:类名::方法名
public interface Sum {
int add(int a, int b);
}
------------------------------->
public class SumUtil {
public static int addMethod(int a, int b){
return a + b;
}
}
------------------------------------------>
Sum sum1 = (a, b) -> SumUtil.addMethod(a,b);
System.out.println("计算结果为:" + sum1.add(10,20));
//简化写法
Sum sum = SumUtil::addMethod;
System.out.println("计算结果为:" + sum.add(10,20));
- 实例方法的引用
lambda表达式对实例方法的引用:
格式:new 构造方法 ::实例方法名
对象::实例方法名
public interface Change {
String toUpper(String s);
}
-------------------------------------->
public class ChangeUtil {
public String upper(String str){
String result = "";
byte[] chars = str.getBytes();
for (byte c:chars) {
result += (char)(c-32);
}
return result;
}
}
-------------------------------------->
Change change1 = s -> new ChangeUtil().upper(s);
System.out.println(change1.toUpper("hello"));
//简化写法
Change change = new ChangeUtil()::upper;
System.out.println(change.toUpper("hello"));
- 类对实例方法引用
方法的引用
类对实例方法引用
类名::实例方法
public class Dog {
private String name;
private Integer age;
private String type;
public Dog(String name, Integer age, String type) {
this.name = name;
this.age = age;
this.type = type;
}
public Dog() {
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + ''' +
", age=" + age +
", type='" + type + ''' +
'}';
}
}
------------------------------------------------>
public interface CreateDog {
//创建Dog对象
Dog creDog();
}
------------------------------------------------->
CreateDog cc = () -> new Dog();
System.out.println(cc.creDog());
//简化写法
CreateDog cc1 = Dog :: new;
System.out.println(cc1.creDog());
- 数组方法引用
public interface CreateArray {
int[] create(int length);
}
--------------------------------->
CreateArray ca = (int length) -> new int[length];
System.out.println(ca.create(5));
//简化写法
CreateArray ca1 = int[]::new;
System.out.println(ca1.create(5));
2.常用接口
2.1 Predicate (条件判断的接口)java8 新特性
接口中默认是抽象方法和常量
接口中可以出现方法体
1 方法有方法体,需要使用default关键词进行修饰
default void a(){
接口中default修饰的方法,可以有方法体,并且实现类可以有选择性的重写
}
2 接口中可以有静态方法
static void a(){
}
import java.util.function.Predicate;
public class Test02 {
public static void main(String[] args) {
Predicate pre = new Predicate(){
@Override
public boolean test(Integer integer) {
return integer > 100;
}
};
System.out.println(pre.test(150));
Predicate pre1 = integer -> integer > 100;
System.out.println(pre1.test(150));
Predicate pre2 = integer -> integer > 10;
Predicate pre3 = integer -> integer > 90;
//50是否大于10 并且 50是否大于90
System.out.println(pre2.and(pre3).test(50));
Predicate pre4 = integer -> integer > 10;
Predicate pre5 = integer -> integer > 90;
//50是否大于10 或者 50是否大于90
System.out.println(pre4.or(pre5).test(50));
Predicate pre6 = integer -> integer > 10;
//20是否大于10,在进行取反
System.out.println(pre6.negate().test(20));
}
}
2.2 Comparator(比较接口)
TreeSet set = new TreeSet<>(new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
TreeSet set1 = new TreeSet<>( (o1,o2) -> o1-o2);
set1.add(20);
set1.add(10);
set1.add(35);
set1.add(30);
System.out.println(set1);
2.3 Function(类型转换接口)
第一个泛型类型的数据转成第二个泛型类型的功能
Function fun = new Function() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
};
Integer apply = fun.apply("123");
System.out.println(apply instanceof Integer); // true
// Function fun1 = (String s) -> {return Integer.parseInt(s);};
// Function fun1 = s -> Integer.parseInt(s);
Function fun1 = Integer::parseInt;
Integer apply1 = fun1.apply("234");
System.out.println(apply1 instanceof Integer); // true
3 lambda表达式+接口应用场景
3.1 stream(集合中的流)
Java8 中添加了一个新的接口类 Stream,相当于高级版的 Iterator,它可以通过 Lambda 表达式对集合进行大批量数据操作,或 者各种非常便利、高效的聚合数据操作。
在 Java8 之前,我们通常是通过 for 循环或者 Iterator 迭代来重新排序合并数据,又或者通过重新定义 Collections.sorts 的 Comparator 方法来实现,这两种方式对于大数据量系统来说,效率并不是很理想。Stream 的聚合操作与数据库 SQL 的聚合操作 sorted、filter、map 等类似。我们在应用层就可以高效地实现类似数据库 SQL 的 聚合操作了,而在数据操作方面,Stream 不仅可以通过串行的方式实现数据操作,还可以通过并行的方式处理大批量数据,提高数据 的处理效率。
水开始流的位置:开始流
水流流过的位置:中间流
水流到山脚下结束:结束流
注意:流都是一次性
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(100);
list.add(25);
list.add(63);
list.add(5);
list.add(105);
list.add(98);
list.add(69);
list.add(25);
}
- filter 判断数据是否满足条件
Stream stream = list.stream();
stream.filter(integer -> integer>50 ).forEach(System.out::println);
- toArray() 将数据保存到数组中
Object[] objects = stream.filter(integer -> integer > 50).toArray();
System.out.println(Arrays.toString(objects)); //[100, 63, 105, 98, 69]
- distinct 去重
Object[] objects = stream.distinct().toArray();
System.out.println(Arrays.toString(objects));
- sorted 排序,默认降序
Object[] objects = stream.sorted().toArray();
System.out.println(Arrays.toString(objects));
自己指定排序条件
Object[] objects = stream.sorted((o1, o2) -> o2 - o1).toArray();
System.out.println(Arrays.toString(objects));
- 中间流进行多次操作,排序 去重 指定条件的数据的显示
Object[] objects = stream.distinct().sorted().filter(integer -> integer >25).toArray();
System.out.println(Arrays.toString(objects)); //[63, 69, 98, 100, 105]
- 数据 指定条数数据的展示
Object[] objects = stream.distinct().sorted().limit(3).toArray();
System.out.println(Arrays.toString(objects));
- max() 最大值、min() 最小值
// Integer integer = stream.distinct().max((o1, o2) -> o1 - o2).get();
// System.out.println(integer); //105
Integer integer = stream.distinct().min((o1, o2) -> o1 - o2).get();
System.out.println(integer); //5
- map 转成其他数据类型
//将所有数据都拼接abc
Object[] objects = stream.distinct().map(s -> s + "abc").toArray();
System.out.println(Arrays.toString(objects)); //[100abc, 25abc, 63abc, 5abc, 105abc, 98abc, 69abc]
doubleValue(全部转换成double类型),longValue(全部转换成long类型),intValue(全部转换成int类型)
// double[] doubles = stream.mapToDouble(Integer::doubleValue).toArray();
// System.out.println(Arrays.toString(doubles)); //[100.0, 25.0, 63.0, 5.0, 105.0, 98.0, 69.0, 25.0]
// long[] longs = stream.mapToLong(Integer::longValue).toArray();
// System.out.println(Arrays.toString(longs)); //[100, 25, 63, 5, 105, 98, 69, 25]
int[] ints = stream.mapToInt(Integer::intValue).toArray();
System.out.println(Arrays.toString(ints)); //[100, 25, 63, 5, 105, 98, 69, 25]
-
reduce 数据运算
//将数组中所有数据相加 Integer integer = stream.reduce((integer1, integer2) -> integer1 + integer2).get(); System.out.println(integer); -
对流中数据进行判断,是否所有的都满足条件 (allMatch)、对流中数据进行判断,是否任意一条数据的都满足条件(anyMatch)、 据进行判断,是否所有数据的都不满足条件 (noneMatch)
// boolean b = stream.allMatch(integer -> integer > 26);
// System.out.println(b); // false
// boolean b = stream.anyMatch(integer -> integer > 26);
// System.out.println(b); // true
boolean b = stream.noneMatch(integer -> integer > 26);
System.out.println(b); // false
- count()数据个数的统计
long count = stream.distinct().count();
System.out.println(count);
4. 可变长参数
方法定义时,可以给方法进行参数个数的不固定个数的指定
public static void main(String[] args) {
List list = Arrays.asList(1, 2, 3, 4, 5, 6);
System.out.println(list);
}
我们从上面的例子可以看出,可变长参数,可以传到多个参数,如果我们不清楚传递多个少个参数,我们可以使用可变长参数。
注意:
1. 一个方法中只能有一个可变长参数,并且可变长参数必须在参数列表最后位置 ;
2. 可变长参数,传入到方法中,它是将所有参数都放到数组中,因此我们方法获取到的可变长参数是一个数组,数组里面存放的我们传入的数据;
public class demo02 {
public static void main(String[] args) {
me(1,2,3,4,5);
me("a","b","c","d");
me(new Student("zs",12), new Student("ls",36), new Student("ww",43));
}
public static void me(T... arr){
System.out.println(Arrays.toString(arr));
}
}



