Java 8 如何将数组转换流

在Java 8中,可以使用Arrays.stream 或 Stream.of 将Array转换为Stream。

1.对象数组

对于对象数组,Arrays.stream 或 Stream.of返回同样的结果。

import java.util.Arrays;
import java.util.stream.Stream;

public class TestJava8 {

    public static void main(String[] args) {

        String[] array = {"a", "b", "c", "d", "e"};

        //Arrays.stream
        Stream<String> stream1 = Arrays.stream(array);
        stream1.forEach(x -> System.out.println(x));

        //Stream.of
        Stream<String> stream2 = Stream.of(array);
        stream2.forEach(x -> System.out.println(x));
    }

}

输出

a
b
c
d
e
a
b
c
d
e

来看看JDK源代码:

Arrays.java

   /**
     * Returns a sequential {@link Stream} with the specified array as its
     * source.
     *
     * @param <T> The type of the array elements
     * @param array The array, assumed to be unmodified during use
     * @return a {@code Stream} for the array
     * @since 1.8
     */
    public static <T> Stream<T> stream(T[] array) {
        return stream(array, 0, array.length);
    }

Stream.java

/**
     * Returns a sequential ordered stream whose elements are the specified values.
     *
     * @param <T> the type of stream elements
     * @param values the elements of the new stream
     * @return the new stream
     */
    @SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
    public static<T> Stream<T> of(T... values) {
        return Arrays.stream(values);
    }

注意:对于object 数组,Stream.of内部调用的是Arrays.stream。

http://w3cschool.codecloud.net/java/java-hello-world.html

2.基础类型数组

对于基础类型的数组,Arrays.stream 和 Stream.of返回的结果不一样。

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class TestJava8 {

    public static void main(String[] args) {

        int[] intArray = {1, 2, 3, 4, 5};

        // 1. Arrays.stream -> IntStream 
        IntStream intStream1 = Arrays.stream(intArray);
        intStream1.forEach(x -> System.out.println(x));

        // 2. Stream.of -> Stream<int[]>
        Stream<int[]> temp = Stream.of(intArray);

        // Cant print Stream<int[]> directly, convert / flat it to IntStream 
        IntStream intStream2 = temp.flatMapToInt(x -> Arrays.stream(x));
        intStream2.forEach(x -> System.out.println(x));

    }

}

输出结果:

1
2
3
4
5
1
2
3
4
5
来看看JDK源代码:
Arrays.java
   /**
     * Returns a sequential {@link IntStream} with the specified array as its
     * source.
     *
     * @param array the array, assumed to be unmodified during use
     * @return an {@code IntStream} for the array
     * @since 1.8
     */
    public static IntStream stream(int[] array) {
        return stream(array, 0, array.length);
    }
Stream.java
   /**
     * Returns a sequential {@code Stream} containing a single element.
     *
     * @param t the single element
     * @param <T> the type of stream elements
     * @return a singleton sequential stream
     */
    public static<T> Stream<T> of(T t) {
        return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
    }

到底用哪个呢?

对于object 数组,2个调用的都是Arrays.stream。 对于基础类型数组,我更喜欢用Arrays.stream,因为它直接返回修正后的IntStream,更容易操作它。

本文最初发表在程序员的资料库

Java Annotations 注解格式与声明

Annotation 的格式

最简单的 Annotation 如下:

@Entity

@ 符号告诉编译器,后面的部分是 Annotation。在下面的例子中 Annotation 的名字是 Override:

@Override
void mySuperMethod() { ... }

Annotation 也可以包含元素,下面的例子说明了如何给 Annotation 元素赋值:

@Author(
   name = "Benjamin Franklin",
   date = "3/27/2003"
)
class MyClass() { ... }

或者

@SuppressWarnings(value = "unchecked")
void myMethod() { ... }

如果只有一个名为 value 的元素,那么元素名称可以省略,例如:

@SuppressWarnings("unchecked")
void myMethod() { ... }

如果 Annotation 中没有元素,那么小括号可以省略,就像上面例子中的 @Override 一样。

可以在同一个声明上面用多个 Annotation,

@Author(name = "Jane Doe")
@EBook
class MyClass { ... }

如果同一个申明上的 Annotation 类型相同,那么就称为重复 Annotation (repeating annotation)

@Author(name = "Jane Doe")
@Author(name = "John Smith")
class MyClass { ... }

重复 Annotation 从 Java 8 开始支持。

预定义的 Annotation 类型在 java.lang 或 java.lang.annotation 包中。在前面的例子中 Override 和 SuppressWarnings 是预定义的 Annotation。Author 和 EBook 是自定义的 Annotation。

Annotation 用在哪里

Java 的声明可以使用 Annotation :类声明,成员变量声明,方法声明和其它声明。

在 Java 8 中,Annotation 还可以用于类型,下面看看例子:

用于创建实例的表达式:

new @Interned MyObject();

用于类型转换:

myString = (@NonNull String) str;

用于 implements 补充:

class UnmodifiableList<T> implements
        @Readonly List<@Readonly T> { ... }

用于声明异常:

void monitorTemperature() throws
        @Critical TemperatureException { ... }

这种 Annotation 被称为类型 Annotation(Type Annotation)。

声明 Annotation 注释

很多 Annotation 都是为了取代代码中传统的注释。例如,假设你编写的代码中有下面这段注释:

public class Generation3List extends Generation2List {
 
   // Author: John Doe
   // Date: 3/17/2002
   // Current revision: 6
   // Last modified: 4/12/2004
   // By: Jane Doe
   // Reviewers: Alice, Bill, Cindy
 
   // class code goes here
 
}

要使用 Annotation 来取代传统的注释,首先需要定义一个 Annotation 类型。语法如下:

@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
   String[] reviewers();
}

定义 Annotation 类型的语法看起来很像定义接口的语法,不过在 interface 关键字前面加了一个 @ 符号。
在上面这个例子中还定义了 Annotation 的元素,定义元素的语法看起来很像定义方法的语法,每个元素都可以使用 default 关键字来定义默认值。

上面的 Annotation 定义之后,你就可以使用它了,并且可以给它的元素赋值,例如:

@ClassPreamble (
   author = "John Doe",
   date = "3/17/2002",
   currentRevision = 6,
   lastModified = "4/12/2004",
   lastModifiedBy = "Jane Doe",
   // Note array notation
   reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {
 
// class code goes here
 
}

注意:如果要让 @ClassPreamble 出现在 Javadoc-generated 生成的文档中,那么需要给它加上 @Documented 注释:

// import this to use @Documented
import java.lang.annotation.*;
 
@Documented
@interface ClassPreamble {
 
   // Annotation element definitions
   
}