首页 » java » 正文

重学java(五)

数组上获得流:Arrays.stream(数组);

数组上获得并行处理流:Arrays.stream(数组).parallel.

集合上获得流:collection.stream();

集合上获得并行流:collection.parallelStream()。

import static java.lang.System.*;
public final class Main{
    public static void main(String args[]){
        int [] a=new int[100];  
        for(int i=0; i<a.length; i++){
            a[i]=(int)(Math.random()*100);  
        }
        OptionalInt result = Arrays.stream(a).parallel()
                .filter(i->i>20)
                .map(i->i*i)
                .sorted()
                .distinct()
                .limit(10)
                .max();  
        out.println(result.isPresent()?result.getAsInt():"无值.");
    }
}

最后一步是max,得到的是一个OptionalInt,表示的是一个可能有值的整数,也可能没有值。

public final class Main{
    public static void main(String args[]){
        Collection<Person> people = Arrays.asList(
                new Person("Ted",18,88),
                new Person("Charlotte", 18,88),
                new Person("Michael",18,99),
                new Person("Matthew", 19,84),
                new Person("Matthew", 21,84)
        );
        Object result = people.parallelStream()
                .filter(p->p.age < 20)
                .sorted((p1,p2)->p1.age -p2.age)
                .sorted(Person::better)
                .sorted(Comparator.comparing(Person::getName))
                .limit(5)
                .mapToDouble(p->p.score)
                .average();  
        System.out.println(result);
    }
}

class Person {
    public String name;
    public int age;
    public double score;
    public Person(String n, int a, double s){
        name=n;  age=a; score=s;
    }
    public String getName(){return name; }
    @Override
    public String toString(){
        return String.format("%s[%d](%f)",name,age,score);
    }
    public static int better(Person p1, Person p2){
        return (int)(p2.score-p1.score);
    }
}

最后结果用了一个Object,其实是个OptionalDouble类型的。

IntStream:整数的流 LongStream:长整数的流 DoubleStream:实数的流

普通的流可以通过mapToInt()等方法来转换成对应的流。

操作流既可以是中间的,又可以是末端的。

中间操作:
filter:过滤
map:通过function对元素执行一对一的替换。
flatMap:将元素转换成更多的元素。
peek:对每个元素执行操作。
distinct:去除重复的元素。
sorted:排序;
limit:限制数量。
substream:限制值的范围。
skip:忽略一些元素。

末端操作:
forEach:对流中的每个元素都执行一些操作。
toArray:将流中的元素放到一个数组里面。
min:
max:
count:计算元素个数。
anyMatch:判断是否有元素匹配设置的断言。
allMatch:判断流中的每个元素是否都匹配断言。
noneMatch:判断是否没有匹配断言的。
findFirst:查找流中的第一个元素。
findAny:查找流中的任意元素。

普遍使用的:
map、flatMap、reduce、collect,需要了解以下。

流实际上指的计算机的输入与输出间运动的序列,流序列中的数据既可以是未加工的二进制数据,也可以是经过一定编码处理的某种格式规定的特定数据。

java.io中的Stream和java.util.stream中的Stream是不同的。

按处理数据的类型,可以分为字节流和字符流。

输入字节流:InputStream 输出字节流:OutputStream
输入字符流:Reader 输出字符流Writer。

InputStream的read:
public int read();
public int read(byte b[]);
public int read(byte[] b, int off, int len);
第一个read是读取一个字节的数据作为低位,再加三个字节组成32为整数返回,如果没有数据,返回-1.
第二个是读取数据保存在b数组中,同时返回读到的字节数目。
第三个读取len个字节,从off位置进行存。

在流的操作中,有个“当前位置”,开始指向第一个数据,随着读取不断后移。
public long skip(long n);后移n个字节
public void mark();当前位置做个标记
public void reset(); 回到标记的地方。
public boolean markSupported();是否支持标记。
public int available();流中有多少字节可读。
public void close();关闭流,必须执行的操作。

OutputStreamde的write()方法:
public void write(int b); 将参数的低位字节写入输出流。
public void write(byte[] b);将数组写入到输出流。
public void write(byte[] b, int off, int len); 将off开始的len个字节写入到流中。
public void flush();
public void close();

write的数据先放在缓冲区中,等缓冲区的数据积累到一定程度时,才统一写到外部设备上,以降低计算机对外部设备的读写次数,提高系统的效率。

Reader的read():
public int read(); //读两个字节
public int read(char b[]);
public int read(char[] b, int off, int len);
与InputStream相比只是读入字符。

Reader也有前面的位置指针对应的那些方法。

Java的字符是两个字节。

public void write(int b); 将参数的低两位字节写入到流中。
public void write(char[] b);将数组写入到输出流。
public void write(char[] b, int off, int len); 将off开始的len个字节写入到流中。
public void flush();
public void close();
public void write(String s); 将字符串写入流中。
public void write(String s, int off, int len);与字符数组类似。

按照流是否直接与特定的地方(磁盘、内存、设备等)相连,分为节点流和处理流。

节点流可以从或向一个特定的地方读写数据,如文件流FileInputStream。

处理流的构造方法,总要带个其他的流对象做参数。

一个流对象经过其他流的多次包装,称为流的链接。

DateInputStream和DataOutputStream定义了多个针对不同数据类型的写操作。

InputStreamReader和OutputStreamWriter能够将字节流转成字符流。

System.in和System.out是System类的两个静态属性。

System的in是InputStream out是OutputStream。

键盘缓冲区没有需要输入的数据,执行输入将会进入阻塞状态。

public final class Main{
    public static void main(String args[]){
        try{
            FileReader input = new FileReader("baidu.htm");
            FileWriter output = new FileWriter("temp.txt");
            int c = input.read();
            while(c!=-1){
                output.write(c);
                System.out.println((char)c);
                c=input.read();
            }
            input.close();
            output.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

注意Reader和Writer是读写一个字符,虽然是转换成整数。

public final class Main{
    public static void main(String args[]){
        try{
            FileReader input = new FileReader("baidu.htm");
            BufferedReader br=new BufferedReader(input);
            FileWriter output = new FileWriter("temp.txt");
            BufferedWriter bw=new BufferedWriter(output);
            String s= br.readLine();
            while(s!=null){
                bw.write(s);
                bw.newLine();
                System.out.println(s);
                s=br.readLine();  
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}
public final class Main{
    public static void main(String args[]){
        String infname = "baidu.htm";
        String outfname = "temp.txt";
        if(args.length >= 1) infname=args[0];
        if(args.length >= 2) outfname=args[1];
        try{
            File fin = new File(infname);
            File fout = new File(outfname);
            BufferedReader in = new BufferedReader(new FileReader(fin));
            PrintWriter out = new PrintWriter(new FileWriter(fout));

            int cnt = 0;
            String s=in.readLine();
            while(s != null){
                cnt++;
                //s=deleteComments(s);
                out.println(cnt+":\t"+s);
                s=in.readLine();
            }
            in.close();
            out.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
    static String deleteComments(String s){
        if(s==null) return s;
        int pos = s.indexOf("//");
        if(pos < 0) return s;
        return s.substring(0, pos);
    }
}

Java对象一般位于内存中,但现实中常要求java虚拟机停止之后能够保存在指定的对象中。

使用java对象序列化,要保存对象时,会把其状态保存为一组字节,在未来再把这些字节组装成对象。

对象序列化保存的是对象的成员变量,不会保存类的静态变量。

只要一个类实现了java.io.Serializable接口,就能被序列化。这个接口没有方法。

序列化就是用ObjectInputStream和ObjectOutputStream进行写入读出。

public final class Main{
    public static void main(String args[]){
        Person[] ps={
                new Person("Li",18),
                new Person("Wang",19)
        };
        String filename="s.temp";

        try{
            ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(filename));
            for(Person p: ps){
                output.writeObject(p);
            }
            Person p=null;
            ObjectInputStream input = new ObjectInputStream(new FileInputStream(filename));
            while((p=(Person)input.readObject())!=null){
                System.out.println(p);
            }
            input.close();
            output.close();
        }catch ( IOException e){

        }
        catch (ClassNotFoundException ex){

        }

    }
}

class Person implements Serializable{
    String name;
    int age;
    Person(String name, int age){
        this.name=name;
        this.age=age;
    }

    public String toString(){
        return name+"("+age+")";
    }
}

对象的序列化不仅会把对象自己序列化,而且还会将对象引用的对象序列化。

如果字段不需要序列化,可以用transitive(意思为过滤的)修饰,表示该字段是瞬态的,不用虚拟化。

ObjectOutputStream有defaultWriteObject()方法,ObjectInputStream有defaultReadObject()方法,进行非静态和transitive的读写操作。

class Person implements Serializable{
    String name;
    int age;
    private void writeObject(ObjectOutputStream out)throws IOException{
        out.defaultWriteObject();
        out.writeInt(age);
    }
    private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException{
        in.defaultReadObject();
        age = in.readInt();  
    }
}

还可以实现Externalizable接口,使用该接口其他的序列化将失效。

方法:
public void writeExternal(ObjectOutput out)throws IOException;
public void readExternal(ObjectInput in)throws IOException;
public void readResolve()throws ObjectStreamException; //处理其他的一些工作。
这种方法要求有不带参数的构造方法,这是通过先构造对象,在进行字段的设置。

发表评论