lambda

map

若map里key对应的value为空,会将第二个参数的返回值存入并返回,不为空就不放入map

// java8之前。从map中根据key获取value操作可能会有下面的操作
Object key = map.get("key");
if (key == null) {
    key = new Object();
    map.put("key", key);
}

// java8之后。上面的操作可以简化为一行,若key对应的value为空,会将第二个参数的返回值存入并返回
Object key2 = map.computeIfAbsent("key", k -> new Object());

List和Map转换

		List<Person> javaProgrammers = new ArrayList<Person>() {
			/**
			* 
			*/
			private static final long serialVersionUID = 1L;

			{
				add(new Person("Elsdon", 2000));
				add(new Person("Tamsen", 1500));
				add(new Person("Floyd", 1800));
				add(new Person("Sindy", 1600));
				add(new Person("Vere", 1200));
				add(new Person("Maude", 1900));
				add(new Person("Shawn", 2300));
				add(new Person("Jayden", 1700));
				add(new Person("Palmer", 2000));
				add(new Person("Addison", 1300));
			}
		};
		
		Map<String,Integer>  map = 	    
				javaProgrammers.stream().collect(
                Collectors.toMap(Person::getName, Person::getAge, 
		        (name, age) -> age, LinkedHashMap::new));

	// Map<String,Integer>  map1 = 	javaProgrammers.stream().collect(Collectors.
    //          toMap(Person::getName, Person::getAge,  (name, age) -> age));


 
		System.out.println(map);

运行结果

{Elsdon=2000, Tamsen=1500, Floyd=1800, Sindy=1600, Vere=1200, Maude=1900, Shawn=2300, Jayden=1700, Palmer=2000, Addison=1300}

		Map<String, Person>  map = 	    
				javaProgrammers.stream().collect(
               Collectors.toMap(Person::getName, e -> e));
		Map<String, Person>  map1 = 	    
				javaProgrammers.stream().collect(
               Collectors.toMap(Person::getName, Function.identity()));	

运行结果 都是

{Shawn=Person [name=Shawn, age=2300], Elsdon=Person [name=Elsdon, age=2000], Palmer=Person [name=Palmer, age=2000], Addison=Person [name=Addison, age=1300], Maude=Person [name=Maude, age=1900], Floyd=Person [name=Floyd, age=1800], Vere=Person [name=Vere, age=1200], Jayden=Person [name=Jayden, age=1700], Tamsen=Person [name=Tamsen, age=1500], Sindy=Person [name=Sindy, age=1600]}

但是上面的方法当key重复时会异常

可以使用下面的方法来解决

		Map<String, Person>  map = javaProgrammers.stream().collect(Collectors.toMap(
           Person::getName, Function.identity(), (key1, key2) -> key2));
		Map<String, Person>  map1 = javaProgrammers.stream().collect(Collectors.toMap(
           Person::getName, Function.identity(), (key1, key2) -> key2, LinkedHashMap::new));

运行结果 都是

{Shawn=Person [name=Shawn, age=2300], Elsdon=Person [name=Elsdon, age=1500], Palmer=Person [name=Palmer, age=2000], Addison=Person [name=Addison, age=1300], Maude=Person [name=Maude, age=1900], Floyd=Person [name=Floyd, age=1800], Vere=Person [name=Vere, age=1200], Jayden=Person [name=Jayden, age=1700], Sindy=Person [name=Sindy, age=1600]}
{Elsdon=Person [name=Elsdon, age=1500], Floyd=Person [name=Floyd, age=1800], Sindy=Person [name=Sindy, age=1600], Vere=Person [name=Vere, age=1200], Maude=Person [name=Maude, age=1900], Shawn=Person [name=Shawn, age=2300], Jayden=Person [name=Jayden, age=1700], Palmer=Person [name=Palmer, age=2000], Addison=Person [name=Addison, age=1300]}
第一个算式的含义:如果key一样,就只保留key最后出现时的对象

第一个算式的含义:如果key一样,就只保留key第一次出现时的对象

2. 聚合函数

	public static void main(String[] args) {
		List<Person> javaProgrammers = new ArrayList<Person>() {
			/**
			* 
			*/
			private static final long serialVersionUID = 1L;

			{
				add(new Person("Elsdon", 2000));
				add(new Person("Elsdon", 1500));
				add(new Person("Floyd", 1800));
				add(new Person("Sindy", 1600));
				add(new Person("Vere", 1200));
				add(new Person("Maude", 1900));
				add(new Person("Shawn", 2300));
				add(new Person("Jayden", 1700));
				add(new Person("Palmer", 2000));
				add(new Person("Addison", 1300));
			}
		};
		
		
		System.out.println(javaProgrammers.stream().collect(Collectors.groupingBy(Person::getName)));
		System.out.println(javaProgrammers.stream().collect(Collectors.counting()));
		System.out.println(javaProgrammers.stream().collect(Collectors.averagingInt(e -> e.getAge())));
		System.out.println(javaProgrammers.stream().collect(Collectors.summingInt(e -> e.getAge())));
		System.out.println(javaProgrammers.stream().collect(Collectors.minBy((e1, e2) -> e1.getAge() -  e2.getAge())).get());
		System.out.println(javaProgrammers.stream().collect(Collectors.maxBy((e1, e2) -> e1.getAge() -  e2.getAge())).get());	
		System.out.println(javaProgrammers.stream().mapToInt(Person::getAge).max().orElse(-1));
		System.out.println(javaProgrammers.stream().collect(Collectors.maxBy((e1, e2) -> e1.getAge() -  e2.getAge())).get());
		System.out.println(javaProgrammers.stream().collect(Collectors.summarizingInt(e -> e.getAge())));
	}

运行结果

{Shawn=[Person [name=Shawn, age=2300]], Elsdon=[Person [name=Elsdon, age=2000], Person [name=Elsdon, age=1500]], Palmer=[Person [name=Palmer, age=2000]], Addison=[Person [name=Addison, age=1300]], Maude=[Person [name=Maude, age=1900]], Floyd=[Person [name=Floyd, age=1800]], Vere=[Person [name=Vere, age=1200]], Jayden=[Person [name=Jayden, age=1700]], Sindy=[Person [name=Sindy, age=1600]]}
10
1730.0
17300
Person [name=Vere, age=1200]
Person [name=Shawn, age=2300]
2300
Person [name=Shawn, age=2300]
IntSummaryStatistics{count=10, sum=17300, min=1200, average=1730.000000, max=2300}
 

flatMap

		List<Person> list = new ArrayList<Person>() {
			/**
			* 
			*/
			private static final long serialVersionUID = 1L;

			{
				add(new Person("andy|koni", 2000));
				add(new Person("Elsdon", 1500));
				add(new Person("Floyd", 1800));
				add(new Person("Sindy", 1600));
				add(new Person("Vere", 1200));
				add(new Person("Maude", 1900));
				add(new Person("Shawn", 2300));
				add(new Person("Jayden", 1700));
				add(new Person("Palmer", 2000));
				add(new Person("Addison", 1300));
			}
		};
		
		 List<String> nameq = list.stream().map(x -> Arrays.asList((x.getName().split("\\|")))).flatMap(x -> x.stream()).collect(Collectors.toList());
		 System.out.println(nameq);
	}

运行结果

[andy, koni, Elsdon, Floyd, Sindy, Vere, Maude, Shawn, Jayden, Palmer, Addison]

重写Person

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Person implements Serializable {
	private static final long serialVersionUID = 1L;
	public Person() {

	}
	
	private List<String> names = new ArrayList<>();
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	private String name;
	
	private int age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}


	public List<String> getNames() {
		return names;
	}

	public void setNames(List<String> names) {
		this.names = names;
	}
	

	@Override
	public String toString() {
		return "Person [names=" + names + ", name=" + name + ", age=" + age + "]";
	}
}

	public static void main(String[] args) {

		
		List<Person> list = new ArrayList<Person>();											
        list.add(new Person());											
        list.add(new Person());											
        list.add(new Person());											
        list.add(new Person());											
        list.add(new Person());											
        											
        list.get(0).getNames().add("DogA5");											
        list.get(1).getNames().add("DogB12");											
        list.get(2).getNames().add("DogA9");											
        list.get(3).getNames().add("DogC11");											
        list.get(4).getNames().add("DogD10");											
        list.get(3).getNames().add("dogc11");											
        list.get(4).getNames().add("dogd10");											
											
        List<String> nameq = list.stream().map(x -> x.getNames()).flatMap(x -> x.stream()).collect(Collectors.toList());											
        System.out.println(nameq);											

	}

运行结果

[DogA5, DogB12, DogA9, DogC11, dogc11, DogD10, dogd10]

::

下面表达等价

        list.stream().map(e -> e.getName()).collect(Collectors.toList());
        list.stream().map(JsonField::getName).collect(Collectors.toList());

e的类型是JsonField,所以可以写成第二种表达式

Function 是要接受一个参数,返回一个参数

比如 我们写个文字串子转数字的函数

原来的写法是

	public static <T extends Number> T string2Number(String value , Class<T> clazz) {
		if (Objects.isNull(value) || value.isEmpty() ) {
			return null;
		}
		if (clazz == BigDecimal.class) {
			return clazz.cast(new BigDecimal(value));
		} else if (clazz == Long.class) {
			return clazz.cast(Long.valueOf(value));
		} else if (clazz == Long.class) {
			return clazz.cast(Integer.valueOf(value));
		} else if (clazz == Float.class) {
			return clazz.cast(Float.valueOf(value));
		}
		return null;
		
	}

可以改写代码

	public static <T extends Number> T string2Number(Function<String, T> function, String numberValue) {
		if (Objects.isNull(numberValue) || numberValue.isEmpty() ) {
			return null;
		}
		return function.apply(numberValue);
	}


string2Number(Long::valueOf, "2")    // ①
string2Number(BigDecimal::new, "2") // ②

string2Number(value -> Long.valueOf(value), "2"); // ③

①和③ 是一样的,③的意思是,传入"2",然后调用 string2Number 函数,当执行到function.apply(numberValue);时,numberValue变成③的value,执行 Long.valueOf(value);

string2Number的Function<String, T> function,其中String是输入参数numberValue的类型,T是function.apply返回的类型

如果没有返回值只有参数的时,用Consumer

如果没有参数只有返回值时,用Supplier

传参返回布尔型用Predicate

前个对象和后个对象比较

	public <T> Predicate<T> nextEquals(Function<? super T, Object> keyExtractor) {
		Deque<T> deque = new ArrayDeque<>();
		return object -> (!deque.isEmpty() && (keyExtractor.apply(deque.pop()).equals(keyExtractor.apply(object)) && deque.add(object)))
				|| !deque.add(object);
	}

		Employee e1 = new Employee("23", 25, 3000, 9922001);
		Employee e2 = new Employee("21", 22, 2000, 5924001);
		Employee e3 = new Employee("John1", 35, 4000, 3924401);
		Employee e4 = new Employee("John2", 55, 3000, 9922001);
		Employee e5 = new Employee("John1", 12, 2000, 5924001);

		List<Employee> employees = new ArrayList<>();
		employees.add(e1);
		employees.add(e2);
		employees.add(e3);
		employees.add(e4);
		employees.add(e5);

        // 要求任意一个前后的Employee 的 name 相同
		System.out.println(employees.stream().anyMatch(nextEquals(Employee::getName)));

先做个stack用来存放当前在对象,

当第一条进来的时候(我们不知道后面下一个的内容,所以要求不比较,并且以不相等作为结果,所以直接返回false):

deque 是空的

通过!deque.isEmpty() 来返回false。但是这时还要把当前对象放入stackdeque 。我们就用|| !deque.add(object)来实现。因为deque.add永远返回true.当执行 !deque.add就是永远返回false,这样就做到 一句代码中不影响结果,并把当前在记录放入stack中。

当后面几条进来时

就会运行到 (keyExtractor.apply(deque.pop()).equals(keyExtractor.apply(object))

stack.pop() 是前面一条记录,object是当前那条记录。来做完比较。

 最后的 && deque.add(object) 是在前面返回true在的时候不影响结果,来把当前在记录放入deque中

distinct

distinct通过传进去的字段

	public <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
		Set<Object> distinctSet = new HashSet<>();
        // T 是 下面的 object, Object 是 keyExtractor.apply(object))的返回值
		return object -> distinctSet.add(keyExtractor.apply(object));
	}
		List<Employee> employeeList = employees.stream()
				 .filter(distinctByKey(Employee::getName))
				.collect(Collectors.toList());

指定长度的stream

        IntStream.range(0, 10).boxed()
                 .collect(Collectors.toList())
                 .forEach(System.out::print);   

  

GROUP BY后 求最大,最小

  Map<String, User> stu1 = list.stream()
                .collect(Collectors.toMap(User::getClassId, Function.identity(),
                        BinaryOperator.minBy(Comparator.comparing(User::getAge))));

  Map<String, Optional<User>> stu2 = list.stream()
                .collect(Collectors.groupingBy(User::getClassId, 
                         Collectors.minBy(Comparator.comparingInt(User::getAge))));

索引

        // 创建一个AtomicInteger
        AtomicInteger index = new AtomicInteger(0);
        List.map(str -> index.getAndIncrement())
            // 打印元素和索引
            .forEach(System.out::println);

結果:

0
1
2

addAndGet()- 以原子方式将给定值添加到当前值,并在添加后返回新值。
getAndAdd() - 以原子方式将给定值添加到当前值并返回旧值。
incrementAndGet()- 以原子方式将当前值递增1并在递增后返回新值。它相当于i ++操作。
getAndIncrement() - 以原子方式递增当前值并返回旧值。它相当于++ i操作。
decrementAndGet()- 原子地将当前值减1并在减量后返回新值。它等同于i-操作。
getAndDecrement() - 以原子方式递减当前值并返回旧值。它相当于-i操作。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值