Java8特性二
题外话
泛型<? super T>
和<? extends T>
class Food {}
class Fruit extends Food {}
class Apple extends Fruit {}
class Banana extends Fruit {}
class Meat extends Food {}
class RedApple extends Apple {}
class GreenApple extends Apple {}
class Plate<T> {
private T item;
public Plate(T t){item = t;}
public T get() {
return item;
}
public void set(T item) {
this.item = item;
}
}
继承关系:
新建一个盘子,set
会报错。
编译器只知道容器内是Fruit
或者它的派生类,但具体是什么类型不知道。所以取的时候要用Fruit
或它的基类。
<? extends Fruit>
会使往盘子里放东西的set( )
方法失效。但取东西get( )
方法还有效(用Fruit
或它的基类)。
使用下界<? super Fruit>
会使从盘子里取东西的get( )
方法部分失效,只能存放到Object
对象里。set( )
方法正常。
Plate<? super Apple> p = new Plate<Fruit>(new Fruit());
Fruit f = p.get(); //error, super所以不确定哪个类能放下,要用Object
Object apple = p.get(); // ok
p.set(new Apple());
p.set(new GreenApple());
p.set(new Fruit()); //error, p放的是apple的超类,所以apple及以下肯定能放,以上不确定
PECS原则 Producer Extends Consumer Super。(相对外界就是producer)频繁往外读取的,适合用上界Extends。经常插入的,适合用下界Super。
Java 8
foreach
List<Integer> list = new LinkedList<>();
list.add(3);
list.add(1);
list.add(2);
for(Integer i:list) {
System.out.println(i);
}
System.out.println("=================");
list.forEach(System.out::println); // 匿名类,lambda,方法引用
//输出:
//3
//1
//2
//=================
//3
//1
//2
数组相关
//迭代函数,生成有序无限的数据流。
IntStream.iterate(2,n->n*3).limit(10).forEach(System.out::println);
//2
//6
//18
//54
//162
//486
//1458
//4374
//13122
//39366
将数组分割成指定大小的小数组
public class Demo {
public static int[][] chunk(int[] numbers,int size) {
return IntStream.iterate(0,i->i+size) //0 3 6
.limit((long)Math.ceil((double) numbers.length/size))
.mapToObj(cur -> Arrays.copyOfRange(numbers, cur, // 0-> [1,4,5], 3->[7,8,9],6->[4,7]
cur + size > numbers.length ? numbers.length : cur + size))
.toArray(int[][]::new);
}
public static void main(String[] args) {
int[] numbers = {1,4,5,7,8,9,4,7};
System.out.println(Arrays.deepToString(chunk(numbers, 3)));
//[[1, 4, 5], [7, 8, 9], [4, 7]]
}
}
concat
强行类型转换没有检查:
public class Demo {
public static <T> T[] concat(T[] first,T[] second) {
return (T[]) Stream.concat(
Stream.of(first),
Stream.of(second)
).toArray();
}
public static void main(String[] args) {
Integer[] numbers = {1,4,5,7,8,9,4,7};
String[] strings = {"12e3","456"};
System.out.println(Arrays.toString(concat(numbers, strings)));
//[1, 4, 5, 7, 8, 9, 4, 7, 12e3, 456]
}
}
有检查:
public class Demo {
public static <T> T[] concat(T[] first,T[] second) {
return Stream.concat(
Stream.of(first),
Stream.of(second)
).toArray(i -> (T[]) Arrays.copyOf(new Object[0], i, first.getClass()));
// 创建一个Object类型的数组,大小为0,Arrays.copyOf(new Object[0], i, first.getClass())
// 返回一个T[10]的全空对象
// 用法:toArray(size -> new String[size])
// 正如上所示,是对的
}
public static void main(String[] args) {
Integer[] numbers = {1,4,5,7,8,9,4,7};
String[] strings = {"12e3","456"};
System.out.println(Arrays.toString(concat(numbers, strings))); // ArrayStoreException
}
}
统计值出现次数
public class Demo {
public static long countOccurrences(int[] numbers, int value) {
return Arrays.stream(numbers)
.filter(i->i==value)
.count();
}
public static void main(String[] args) {
int[] numbers = {1,4,5,7,8,9,4,7};
System.out.println(countOccurrences(numbers,4));
}
}
还有很多小例子,慢慢看吧: biezhi/30-seconds-of-java8
参考
Java 泛型 <? super T> 中 super 怎么 理解?与 extends 有何不同? - 胖君的回答 - 知乎