[JAVA8 the new features of the stream]

The reason to write this section originated in the following code:

Optional<KeywordRouter> optional = getAllKeywordRouter().stream().filter(predicate -> predicate.getOriginKeyword().equals(originKeyword)).findFirst();

List<RfaPublicBean> rfaPublicResponseBeans = rfaPublicBeanPagedList.getList().parallelStream().map(this::converter).collect(Collectors.toList());

White Look at the code when they are dizzy. . When thinking about themselves in order to write this code. .

Analysis:
This code uses the stream List collection class () method to get a Stream object; then call filter () and filtered to give the desired object; followed by Optional objects; filtering process using lamda expression.

Related to the point: [new features] JAVA8

  • There implement abstract interface default method
  • Collection stream interface () method and parallelStream () method
  • Various methods Stream Interface
  • filter () function in the interface
  • optional class ( specifically see text )
  • lamda expression and colon double usage

The abstract interface default method

Collection of the interface has a plurality of default implementation of the method , where they talk stream () method and parallelStream () method implements this interface by default with this method.

public interface Collection<E> extends Iterable<E> {
	//...
	
	default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

	default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
    
    // ...
}

These two methods What difference does it make? Look at the following code:

public static void main(String[] args){		
	List<Integer> i=Arrays.asList(1,2,3,4,5,6,7);
	i.stream().forEach(System.out :: println);//固定结果 1234567
	i.parallelStream().forEach(System.out :: println);//每次的结果都不同
	i.parallelStream().forEachOrdered(System.out :: println);//结果同stream.forEach		       
}

parallelStream () is a parallel operation, the data is divided into a plurality of segments, each of which is processed in a different thread, and then outputs the results together. parallelStream efficiency than traditional for loop and stream much faster

So when to use stream or parallelStream it? You can start to consider the following three points

  • The need for parallel?
  • Whether it is independent of each task? Whether it will cause any race conditions?
  • The results depend on whether the calling sequence of tasks?

Stream Interface

Stream is not a collection of elements, it is not a data structure of the data is not saved, it is about algorithms and calculations, it is more like an advanced version of Iterator. The original version of the Iterator, a user can explicitly through the elements and perform a certain operation; Advanced versions Stream, as long as the user needs to perform any given operation of its contained elements, such as "filter out length greater than 10 string "," Get the first letter of each string "and, implicitly Stream traversed internally converting the data accordingly.

Stream like an iterator (the Iterator), unidirectional, not reciprocating, data can only be traversed once traversed once after exhausted, like water flows from the front, gone.

And while the iterator is different and, in parallel Stream operation, only imperative iterators, the serialization operation. As the name suggests, when a serial mode to traverse, and then read each item to read the next item. When used to traverse the parallel data it is divided into a plurality of segments, each of which is processed in a different thread, and then outputs the results together. Fork Stream dependent parallelism introduced in Java7 / Join frame (JSR166y) to accelerate the process and split task.

It listed the following common methods:

public interface Stream<T> extends BaseStream<T, Stream<T>> {
	// 过滤流
	Stream<T> filter(Predicate<? super T> predicate);
	// 找到流中最小的
	Optional<T> min(Comparator<? super T> comparator);
	// 找到流中最大的
	Optional<T> max(Comparator<? super T> comparator);
	// 流中是否有满足条件的
	boolean anyMatch(Predicate<? super T> predicate);
	// 流中是否都满足条件
	boolean allMatch(Predicate<? super T> predicate);
	// 流中是否都不匹配
	boolean noneMatch(Predicate<? super T> predicate);
	// 流中找到第一个
	Optional<T> findFirst();
	// 流中找到任意一个
	Optional<T> findAny();
	// 这个方法传入一个Function的函数式接口,这个接口,接收一个泛型T,返回泛型R
	// map函数的定义,返回的流,表示的泛型是R对象,这个表示,调用这个函数后,可以改变返回的类型
	<R> Stream<R> map(Function<? super T, ? extends R> mapper);
	
	void forEach(Consumer<? super T> action);
	
	// ...
}

Stream <T> filter (Predicate <? Super T> predicate) to filter incoming stream according to lamada expression. Important difference map method and the method is to return the value of the filter, with the output map can be mapped to different types of parameters, but merely filter filtering the original stream. Predicate Function and a function interface.

Functional Interface

JDK 1.8 API includes many built-in functions interface, common to the Runnable interface such as Comparator or old Java, these interfaces can be used to increase the @FunctionalInterface comment on lambda.

name type description
Consumer Consumer< T > Receiving the object T, does not return value
Predicate Predicate< T > Receiving the object and returns a boolean T
Function Function< T, R > T receiving object, and returns the object R
Supplier Supplier< T > Providing an object T (e.g. plant) does not receive a value
UnaryOperator UnaryOperator T receiving object, and returns the object T
BinaryOperator BinaryOperator T receives two objects, the object returns T

Labeled FunctionalInterface interface is called a function interface, the interface can have a custom method, but may include methods inherited from the object class is derived. If a method is only one interface, the compiler will think this is a function interface. Whether it is a function interface, you need to pay attention to the following points:

  • The only comment mark "one and only oneAbstract method"On the interface.
  • JDK8 interface static methods and the default method, is not regarded as abstract methods.
  • Interface default inherit java.lang.Object, so if the interface displays a statement covering the Object methods, so not too abstract methods.
  • The comment is not required, if an interface matching "function interface" is defined, then did to the notes are not affected. Plus the notes to better allow the compiler to be checked. If writing is not functional interface, but added @FunctionInterface, then the compiler will complain.
  • Two methods defined in a custom interface, will produce Invalid '@FunctionalInterface' annotation; FunctionalInterfaceTest is not a functional interface errors.

Predicate Interface

Predicate functions primary role is to provide an interface test method, based on the incoming lambda expression determined, accepts a parameter returns a Boolean type, some Predicate determined when the stream api very common.

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
    
	//...
}

In addition, Predicate also provides three additional default method and two static methods ( JAVA8 new features ).

  • and a method of receiving Predicate type, is incoming to the current conditions and the conditions and the relationship filtered data.
  • or a method of receiving the same type Predicate, incoming current conditions and filtering conditions to the data or relation.
  • negate the current condition is negated. Look at specific use

Next we look at three important ways Predicate default implementation of and, or, and negate the corresponding three connection of symbols && java, || and!.

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }

    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}

test:

int[] numbers= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
List<Integer> list=new ArrayList<>();
for(int i:numbers) {
	list.add(i);
}
Predicate<Integer> p1=i->i>5;
Predicate<Integer> p2=i->i<20;
Predicate<Integer> p3=i->i%2==0;
List test=list.stream().filter(p1.and(p2).and(p3)).collect(Collectors.toList());
System.out.println(test.toString());
/** print:[6, 8, 10, 12, 14]*/

Function Interface

Source part:

@FunctionalInterface
public interface Function<T, R> {

    // 将Function对象应用到输入的参数上,然后返回计算结果
    R apply(T t);

    // 返回一个先执行before函数对象apply方法再执行当前函数对象apply方法的函数对象
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    // 返回一个先执行当前函数对象apply方法再执行after函数对象apply方法的函数对象。
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * Returns a function that always returns its input argument.
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Except that compose and andThen function to execute a different order. compose function executed first parameter, and then execute the caller, but the caller andThen executed first, and then perform parameter.

Double colon usage

Double colon is the method java operator references, method references format:: class name method name.
Here is the method name, followed by the method name without parentheses "()." --------> This formula does not represent the will call this method. This formula is generally used as a Lambda expressions, Lambda so-called lazy loading, the brackets do not say, look at the situation calling the method.

For example:
the expression:

person ->person.getAge();

It can be replaced with:

Person::getAge

expression:

()-> new HashMap<>();

Can be replaced

HashMap::new

This reference method or a double colon operator corresponding to the parameter type isFunction<T,R>, T represents the incoming type, R represents the return type. Expressions such person -> person.getAge (); incoming parameter is person, the return value is peron.getAge (), then the method references corresponding to Person :: getAge Funciton <Person, Integer> type.

Sample code: Inside the List of all caps String and returns a new ArrayList, in the previous example is written.

List<String> collected = new ArrayList<>();
collected.add("alpha");
collected.add("beta");
collected = collected.stream().map(string -> string.toUpperCase()).collect(Collectors.toList());
System.out.println(collected); 

After programming the following form double colon operator:

List<String> collected = new ArrayList<>();
collected.add("alpha");
collected.add("beta");
collected = collected.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collected); 

Reference links: https://segmentfault.com/a/1190000012256677?utm_source=tag-newest
Reference Links: https://blog.csdn.net/huo065000/article/details/78964382
Reference Links: HTTPS: //www.cnblogs .com / hengzhou / p / 9550250.html

Published 33 original articles · won praise 9 · views 8694

Guess you like

Origin blog.csdn.net/Serena0814/article/details/97135073