学习jdk1.8——day3

类型推断:
你还可以进一步简化你的代码。
Java编译器会从上下文(目标类型)推断出用什么函数式接口来配合Lambda表达式,这意味着它也可以推断出适合Lambda的签名,因为函数描述符可以通过目标类型来得到。这样做的好处在于,编译器可以了解Lambda表达式的参数类型,这样就可以在Lambda语法中省去标注参数类型。

List<String> list = 
	new ArrayList<>();

lambda表达式:
方法引用: 简化lambda,重复利用已有的代码

方法引用让你可以重复使用现有的方法定义,并像Lambda一样传递它们。
方法引用可以被看作仅仅调用  【特定方法的Lambda】 的一种快捷写法。
当你需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面。

1,引用构造器
	Supplier<类名> 变量名 = 类名::new
	Student stu = 变量名.get();

2,引用有参数构造器
	BiFunction<参数1, 参数2, 类名>  bf = 类名::new;
	类名 变量名 = bf.apply(值1,值2);

2.5,引用数组构造器
	IntFunction<int[]> arrayMaker = int[]::new;
	int[] array = arrayMaker.apply(10);


3,引用静态方法
	函数接口类型 变量名 = 类名::静态方法名

4,普通方法的引用:
	函数接口类型 变量名 = 对象::方法名;

5,实例方法引用

	类名::方法名A;
	将lambda的参数 直接当做 A方法的参数
	
	这种写法,不讨论返回值的问题。有就自动返回。
    1,如果lambda的参数正好和::后面方法A的参数一样
      那么就是调用::后面的方法A,把lambda的参数传进去
        // R apply(T t);
	Consumer<String> f = System.out::println;
	Consumer<String> f1 = (t)->{System.out.println(t);};
	
	// void accept(T t, U u);
	BiConsumer<Integer,Integer> bc = (a,b)->{Math.max(a, b);};
	BiConsumer<Integer,Integer> bc1 =  Math::max;
	

    2,如果lambda的参数 比::后面方法A的参数多
      那么就是第一个参数调用::后面方法A,把lambda剩下的参数传入::后面的方法A
	// R apply(T t);
	Function<String,String> fun1 = String::toUpperCase;
	Function<String,String> fun = (t)->t.toUpperCase();
	
	// void accept(T t, U u);
	BiConsumer<String,Integer> bc = String::substring;
	BiConsumer<String,Integer> bc1 = (a,b)->{a.substring(b);};

Optional类 : 可选择的

作用:防止NullPointerException异常的辅助类型
取值:null 或者 不是null

Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional。
这是一个可以为null的容器对象。

如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional的使用:

1,创建Optional:
1.Optional.of(值);
为非null的值创建一个Optional,如果这个值为null报错
2,Optional.ofNullable(值);
为值创建一个Optional,如果值为null,则返回一个空的Optional
代码:Optional.ofNullable(null);
返回结果 : Optional.empty
2,使用:
1,isPresent();
如果值不为空返回true,否则返回false
2,get();
如果有一个值,返回值,否则抛出 NoSuchElementException
3,ifPresent(Consumer<? super T> consumer)
如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。
Optional o1 = Optional.of(“tom”);
Optional o2 = Optional.ofNullable(null);
o1.ifPresent(System.out::println);
o2.ifPresent(System.out::println);//不执行
4,orElse(T other)
值如果存在返回值,否则返回 other 。
System.out.println(o1.orElse(“aaa”));//o1,不为null返回原值
System.out.println(o2.orElse(“aaa”));//o2,为null 返回aaa
5,orElseGet(Supplier<? extends T> other)
返回值(如果存在),否则调用 other并返回该调用的结果。
将操作的结果当做other值
6,orElseThrow(Supplier<? extends X> exceptionSupplier)
返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。
7,map(Function<? super T,? extends U> mapper)
如果存在一个值,则应用提供的处理函数,如果结果不为空,则返回一个 Optional结果的 Optional 。为null抛异常

 	Optional<Integer> map = o1.map(str->1);
 	System.out.println(map.get());
 8,flatMap(Function<? super T,Optional<U>> mapper) 
 	如果一个值存在,应用提供的 Optional映射函数给它,返回该结果,否则返回一个空的 Optional 。 
 	
 	Optional<String> o3 = o1.flatMap(a->Optional.of("10"));
 	System.out.println(o3.get());
 区别 :  flatMap中的mapper返回值必须是Optional;flatMap不会对返回值自动封装为Optional类型
 9,filter(Predicate<? super T> predicate) 
 	如果一个值存在,并且该值给定的断言相匹配时,返回一个 Optional描述的值,否则返回一个空的 Optional 。 
 	
 	Optional<String> filter = o1.filter(str->str.length()<2);
 	System.out.println(filter);

Stream : 流水线

流水线 : 对数据的一组操作


jdk8,添加了新的类java.util.Stream:
Java8中的Stream是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利高效的聚合操作,或者大批量数据操作
Stream的API结合Lambda表达式,极大的提高编程效率和程序可读性
同时它提供串行和并行两种模式进行操作

流操作
java.util.stream.Stream中的Stream接口定义了许多操作。
它们可以分为两大类。
1,中间操作 : 可以连接起来的流操作
2,终端操作 : 关闭流的操作
终端操作会从流的流水线生成结果。
其结果是任何不是流的值,比如ListInteger,甚至void。
注:除非流水线上触发一个终端操作,否则中间操作不会执行任何处理。

使用流
流的使用一般包括三件事:
1,一个数据源(如集合)来执行一组操作;
2,一个中间操作链,形成一条流的流水线;
3,一个终端操作,执行流水线,并能生成结果。

4,Stream对象的构建
    1.使用值构建
	Stream<String> stream = Stream.of("a", "b", "c");
    2. 使用数组构建
	String[] strArray = new String[] {"a", "b", "c"};
	Stream<String> stream = Stream.of(strArray);
	Stream<String> stream = Arrays.stream(strArray);
    3. 利用集合构建(不支持Map集合)
	List<String> list = Arrays.asList(strArray);
	stream = list.stream();
    注:基本数据类型的流:IntStream ,LongStream,DoubleStream
	不要选用Stream<Integer>,Stream<Long>,Stream<Double>因为自动装箱耗时,效率低
	Java 8 中还没有提供其它基本类型数值的Stream
    4,IntStream:数值Stream的构建:
	IntStream s1 = IntStream.of(new int[]{1, 2, 3});
	//[1,3)
	IntStream s2 = IntStream.range(1, 3);
	//[1,3]
	IntStream s3 = IntStream.rangeClosed(1, 3);

Stream转换为其它类型:
Stream stream = Stream.of(“hello”,“world”,“tom”);
1,转换为Array
String[] strArray = stream.toArray(String[]::new);
2,转换为Collection
List list1 = stream.collect(Collectors.toList());
List list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set set3 = stream.collect(Collectors.toSet());
Set set4 = stream.collect(Collectors.toCollection(HashSet::new));
3. 转换为String
String str = stream.collect(Collectors.joining()).toString();

注意 : 一个 Stream 只可以使用一次,上面的代码为了简洁而重复使用了多次。
	这个代码直接运行会抛出异常的:
	java.lang.IllegalStateException: stream has already been operated upon or closed

流操作
中间操作 : Intermediate
map
map(Function<? super T,? extends R> mapper)
返回由给定函数应用于此流的元素的结果组成的流。

		eg:把 Stream中 的每一个元素,映射成另外一个元素
		public static void main(String[] args) throws Exception {
			Stream<String> stream = Stream.of("tom","lisi","wangwu");
			//R apply(T t);
			Function<String,String> fun = (t)->t.toUpperCase();
			List<String> list = stream.map(fun).collect(Collectors.toList());
			System.out.println(list);
		}
	
	filter : 
		filter(Predicate<? super T> predicate)
		返回由与此给定谓词匹配的此流的元素组成的流。

		eg:获取字符串中长度大于3的字符串
		 public static void main(String[] args) throws Exception {
			Stream<String> stream = Stream.of("tom","lisi","wangwu","a");
			List<String> list = stream.filter((msg)->msg.length()>3).collect(Collectors.toList());
			// boolean test(T t);
			// Predicate<T>
			System.out.println(list);
		}  
	
	peek : 偷看,可以用来检查流当前的状态。
		(Consumer<? super T> action) 
		对每个元素执行操作并返回一个新的 Stream
		注意:调用peek之后,一定要有一个最终操作
		public static void main(String[] args) throws Exception {
			Stream<String> stream = Stream.of("tom","lisi","wangwu");
			stream.filter(e -> e.length() > 3)
				  .peek(e -> System.out.println("符合条件的值为: " + e))
				  .collect(Collectors.toList());
		}

	distinct
		返回由不同元素组成的流
	sorted
		返回由此流的元素组成的流,根据自然顺序排序。
	sorted(Comparator<? super T> comparator)
		返回由此流的元素组成的流,根据自然顺序排序。
	limit	
		limit(long maxSize)
		限制流的长度不超过maxSize

		public static void main(String[] args) throws Exception {
			Stream<String> stream = Stream.of("tom","lisi","wangwu","hhhhhh","werwerwefwe");
			stream.filter(e -> e.length() > 3)
				  .peek(e -> System.out.println("符合条件的值为: " + e)).limit(2)
				  .collect(Collectors.toList());
		}
		满足条件的有多个,但是最终返回的集合中只有两个数据。
	skip	
		skip(long n);
		跳过多少个元素
			public static void main(String[] args) throws Exception {
				Stream<String> st = Stream.of("tom","lisi","wangwu","zhaoliu");
				List<String> list = st.skip(2).collect(Collectors.toList());
				System.out.println(list);
			}
		最终打印[wangwu, zhaoliu]

	parallel  :  并行 
	sequential : 有顺序

终端操作 : Terminal
	forEach 
		遍历 接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。
		
		stream.forEach(System.out::println);
	findFirst 
		总是返回 Stream 的第一个元素,或者空,返回值类型:Optional。
		如果集中什么都没有,那么list.stream().findFirst()返回一个Optional<String>对象,但是里面封装的是一个null。
		
		public static void main(String[] args) throws Exception {
			Stream<String> stream = Stream.of("hello","world","tom");
			Optional<String> findFirst = stream.findFirst();
			System.out.println(findFirst);
		}
	
	anyMatch 
		allMatch(Predicate<? super T> predicate) 
		任意一个匹配成功返回true
	allMatch
		allMatch(Predicate<? super T> predicate) 
		所有匹配成功才返回true
	noneMatch 
		noneMatch(Predicate<? super T> predicate)
		没有一个匹配的就返回true 否则返回false
	
	count	计数
		返回Stream中元素的个数,返回值类型是long。


	reduce 合并
		允许通过指定的函数来将stream中的多个元素规约合并为一个元素.
		
		它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max等都是特殊的 reduce。
		
		eg1:
			1-10累加
			IntStream red = IntStream.range(1, 10);
			Integer sum = red.reduce(0, (a, b) -> a+b);
			System.out.println(sum);
		eg2:
			拼接字符串
			String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
			System.out.println(concat);
		eg3:
			List<String> list = Arrays.asList("test","javac","hello","world","java","tom","C","javascript");
			Optional<String> reduce = list.stream().sorted((s1,s2)->s2.length()-s1.length()).filter(s->s.startsWith("j")).map(s->s+"_briup").reduce((s1,s2)->s1+"|"+s2);
			System.out.println(reduce.orElse("值为空"));
			//javascript_briup|javac_briup|java_briup
	
	max:
		max(Comparator<? super T> comparator) 
		根据提供的 Comparator返回此流的最大元素。 
		String[] arr= {"zom","lisi","wagnwu"};
		Stream<String> stream = Arrays.stream(arr);
		Optional<String> max = stream.max(String::compareTo);
		System.out.println(max.get());//zom
	min:
		min(Comparator<? super T> comparator) 
		根据提供的 Comparator返回此流的最小元素。 
		
		String[] arr= {"zom","lisi","wagnwu"};
		Stream<String> stream = Arrays.stream(arr);
		Optional<String> max = stream.min(String::compareTo);
		System.out.println(max.get());//lisi

	forEachOrdered
		如果流具有定义的遇到顺序,则以流的遇到顺序对该流的每个元素执行操作。 
		Stream<String> stream = Stream.of("tom","lisi");
		stream.forEachOrdered((a)->{System.out.println(a);});

	toArray 
		toArray(IntFunction<A[]> generator) 
		使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。 
		Stream<String> stream = Stream.of("tom","lisi");
		String[] array = stream.toArray(String[]::new);
	collect 
		collect(Collector<? super T,A,R> collector) 
		使用 Collector对此流的元素执行 mutable reduction Collector 。  
		
		Stream<String> stream = Stream.of("tom","lisi");
		List<String> list = stream.collect(Collectors.toList());
		Set<String> set = stream.collect(Collectors.toSet());
	findAny
		返回描述流的一些元素的Optional如果流为空,则返回一个空的Optional 
	iterator
		获得迭代器

短路操作 : Short-circuiting: 
	anyMatch
	allMatch
	noneMatch
	findFirst
	findAny 
	limit

Stream.generate
自己来控制Stream的生成
这种情形通常用于随机数、常量的 Stream,或者需要前后元素间维持着某种状态信息的 Stream。
把 Supplier 实例传递给 Stream.generate() 生成的 Stream,由于它是无限的,在管道中,必须利用limit之类的操作限制Stream大小。
可以使用此方式制造出海量的测试数据

eg:
	生成100个随机数并由此创建出Stream实例
	Stream.generate(()->(int)(Math.random()*100)).limit(100).forEach(System.out::println);

工具类:Collectors
java.util.stream.Collectors 类
主要作用就是辅助进行各类有用的操作。

eg1:
	把Stream中的元素进行过滤然后再转为List集合
	List<String> list = Arrays.asList("test","hello","world","java","tom","C","javascript");
	List<String> result = list.stream().filter(s->s.length()>4).collect(Collectors.toList());

串行和并行
串行Stream上的操作是在一个线程中依次完成
并行Stream则是在多个线程上同时执行

串行和并行的相互转换:

可以通过对收集源调用parallelStream方法来把集合转换为并行流。
对顺序流调用parallel方法把流转换成并行流。

并行流就是一个把内容分成多个数据块,并用不同的线程分别处理每个数据块的流。

对顺序流调用parallel方法并不意味着流本身有任何实际的变化。它在内部实际上就是设了一个boolean标志,表示你想让调用parallel之后进行的所有操作都并行执行。
只需要对并行流调用BaseStream下的sequential()方法就可以把它变成顺序流。

并行测试:
public static void main(String[] args) {
//生成100万个不同的字符串放到集合中
int max = 1000000;
List values = new ArrayList(max);
for (int i = 0; i < max; i++) {
UUID uuid = UUID.randomUUID();
values.add(uuid.toString());
}
//1纳秒*10^9=1秒
long t0 = System.nanoTime();
//串行stream
long count = values.stream().sorted().count();
//并行stream
//long count = values.parallelStream().sorted().count();
long t1 = System.nanoTime();

   long time = t1 - t0;
   System.out.println(count);
   System.out.println(time);
}

Map集合: HashMap

Map类型不支持stream
Java8为Map新增的方法
	
   基础数据:
	Map<String, Integer> map = new HashMap<>();
	map.put("tom",1);
	map.put("lisi",2);
	map.put("wangwu",3);
	map.put("zhaoliu",4);
	map.put("zhangsan",null);

Object compute(Object key, BiFunction remappingFunction):
	该方法使用remappingFunction根据原key-value对计算一个新的value。
	只要新的value不为null,就使用新的value覆盖原value;
	如果新的value为null,则删除原key-value对;
	
	// BiFunction<? super K, ? super V, ? extends V>
	//  R apply(T t, U u);
	BiFunction<String, Integer, Integer> bif = (key,value)->{
		return 20;
	};
	map.compute("tom", bif);//替换tom的值
	map.compute("lisi", (key,value)->33);//替换lisi的值

Object computeIfAbsent(Object key, Function mappingFunction):
	如果传入的key参数在Map中对应的value为null,
		该方法将使用mappingFunction根据原key、value计算一个新的结果,
		则用该计算结果覆盖原value;
	如果传入的key参数在Map中对应的value不为null,则该方法不做任何事情;
	如果原Map原来不包括该key,该方法可能会添加一组key-value对。
	
	value为null:
		map.computeIfAbsent("zhangsan", (key)->19);
		System.out.println(map);
	value不为null:
		map.computeIfAbsent("zhaoliu", (key)->19);
		System.out.println(map);
	key不存在:
		map.computeIfAbsent("a", (key)->19);
		System.out.println(map);

Object computeIfPresent(Object key, BiFunction remappingFunction):
	并且该计算结果不为null,则使用该结果覆盖原来的value;
	
	//R apply(T t, U u);
	map.computeIfPresent("zhaoliu", (key,value)->10);
	System.out.println(map);

void forEach(BiConsumer action):
	该方法是Java8为Map新增的一个遍历key-value对的方法。
	
	map.forEach((key,value)->{
		System.out.println(key+"--"+value);
	});

Object getOrDefault(Object key, V defaultValue):
	获取指定的key对应的value。如果该key不存在,则返回defaultValue。
	
	System.out.println(map.getOrDefault("zhaoliu", 10));//4
	System.out.println(map.getOrDefault("a", 10));//10

Object merge(Object key, Object value, BiFunction remappingFunction):
	该方法会先根据key参数获取该Map中对应的value。
	如果获取的value为null,则直接使用传入的value覆盖原value。
	如果获取的value不为null,则使用remappingFunction函数根据原value、新value计算一个新的结果,并用新的结果去覆盖原有的value。
	
	key对应的value为null:
		map.merge("zhangsan", 20, (key,value)->{return value+1;});
		System.out.println(map);
		//zhangsan=20

	key对应的value不为null:
		map.merge("zhaoliu", 20, (key,value)->{return value+1;});
		System.out.println(map);
		//{zhaoliu=21}

Object putIfAbsent(Object key, Object value):
	该方法会自动检测指定的key对应的value是否为null,
	如果该key对应的value为null,则使用传入的新value代替原来的null。
	如果该key对应的value不是null,那么该方法不做任何事情。
	
	key对应value为null:
		map.putIfAbsent("zhangsan", 20);
		System.out.println(map);
		//zhangsan=20

	key对应value不为null:
		map.putIfAbsent("wangwu", 20);
		System.out.println(map);
		//wangwu=3
			
Object replace(Object key, Object value):
	将Map中指定key对应的value替换成新value并把被替换掉的旧值返回。
	如果key在Map中不存在,该方法不会添加key-value对,而是返回null。
	
	map.replace("lisi", 42);
	System.out.println(map);
	//lisi=42

Boolean replace(K key, V oldValue, V newValue):
	将Map中指定的key-value对的原value替换成新value。
	如果在Map中找到指定的key-value对,则执行替换并返回true,否则返回false。
	
	key-value都正确
		map.replace("lisi", 2, 23);
		System.out.println(map);
		//lisi=23//替换成功
	key-value没有都正确
		map.replace("lisi", 21, 23);
		System.out.println(map);
		//lisi=2//替换失败

replaceAll(BiFunction function):
	该方法使用function对原key-value对执行计算,
	并将计算结果作为key-value对的value值

	map.replaceAll((key,value)->{return value!=null?value+1:0;});
	System.out.println(map);
	{lisi=3, tom=2, zhaoliu=5, zhangsan=0, wangwu=4}

Date:
最原始:注:本次用到的Date都是java.util.Date
1,创建时间
//当前时间
java.util.Date d = new java.util.Date();
//某个时间戳创建时间
//时间戳 : 1970-01-01到某个日期的毫秒数
java.util.Date d1 = new java.util.Date(12310231231L);

   2,将字符串解析为时间Date类型
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	String msg = "2019-8-28 7:41:07";
	Date parse = sdf.parse(msg);
	System.out.println(parse.toLocaleString());

   3,将日期Date类型格式化为字符串:
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	String format = sdf.format(new Date());
	System.out.println(format);

新:提供了java.time包下的类处理日期
	java.time – 包含值对象的基础包
	java.time.chrono – 提供对不同的日历系统的访问
	java.time.format – 格式化和解析时间和日期
	java.time.temporal – 包括底层框架和扩展特性
	java.time.zone – 包含时区支持的类			
   新增:
	创建日期:
		//创建指定时间
		LocalDate date = LocalDate.of(2019, Month.OCTOBER, 28);
		System.out.println(date.toString());

		//创建当前时间
		LocalDateTime now = LocalDateTime.now();
		
		//创建指定时间
		LocalDateTime ldt = LocalDateTime.of(2019, 8, 28, 7, 49, 28);
		System.out.println(ldt.toString());
	
	格式化日期:
	   将字符串转换为日期
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		String time= "2019-08-28";
		LocalDate dl1 = LocalDate.parse(time, dtf);
		String str1 = dl1.format(dtf);
		System.out.println(str1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值