用Java8 Stream和 Lambda表达式来解析文件的一个例子

最近我想从一个日志文件中提取出指定的数据,下面是日志的一部分:

2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: eVentToRequestsBolt __ack_ack [-6722594615019711369 -1335723027906100557]
2	2015-01-06 11:33:03 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar
3	2015-01-06 11:33:04 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557]
4	2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo
5	2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz

我准备使用Java8中Stream和Lambda表达式来完成这件事。

读取文件

首先我要读物日志文件然后将日志的每一行放入一个Stream中。

Stream<String> lines = Files.lines(Paths.get(args[1]));

过滤相关的行

我需要得到包名并将它写入到另一个文件中,并不是所有的行都包含我想要的数据,因此仅过滤相关的行。

lines.filter(line -> line.contains("===---> Loaded package"))

解析相关行

接下来,我要解析相关的行。我将每一行数据分割到一个字符串数组中然后获取这个数组的最后一个元素。换句话说,我进行了两次mapping。首先从一行数据到一个数组然后从一个数组到一个字符串。

.map(line -> line.split(" "))
.map(arr -> arr[arr.length - 1])

写到输出文件

最后一步,将每一个字符串写入到输出文件。这是最后的操作。

.forEach(package -> writeToFile(fw, package));

writeToFile是我自定义的一个方法。这么做的理由是Java文件系统会抛出IOException,但在Lambda表达式中不能使用受检查异常。

下面是完整的代码:

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class App {
	public static void main(String[] args) throws IOException {
		Stream<String> lines = null;
		if (args.length == 2) {
			lines = Files.lines(Paths.get(args[1]));
		} else {
			String s1 = "2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: adEventToRequestsBolt __ack_ack [-6722594615019711369 -1335723027906100557]";
			String s2 = "2015-01-06 11:33:03 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557]";
			String s3 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar";
			String s4 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo";
			String s5 = "2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz";
			List<String> rows = Arrays.asList(s1, s2, s3, s4, s5);
			lines = rows.stream();
		}

		new App().parse(lines, args[0]);

	}

	private void parse(Stream<String> lines, String output) throws IOException {
		final FileWriter fw = new FileWriter(output);

		//@formatter:off
		lines.filter(line -> line.contains("===---> Loaded package"))
		.map(line -> line.split(" "))
		.map(arr -> arr[arr.length - 1])
		.forEach(package -> writeToFile(fw, package));
		//@formatter:on
		fw.close();
		lines.close();
	}

	private void writeToFile(FileWriter fw, String package) {
		try {
			fw.write(String.format("%s%n", package));
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

}

原文地址:http://www.javacodegeeks.com/2015/01/java-8-stream-and-lambda-expressions-parsing-file-example.html

时间: 2024-10-29 19:11:50

用Java8 Stream和 Lambda表达式来解析文件的一个例子的相关文章

Java8一:Lambda表达式教程

1. 什么是λ表达式 λ表达式本质上是一个匿名方法.让我们来看下面这个例子: public int add(int x, int y) {         return x + y;     } 转成λ表达式后是这个样子:         (int x, int y) -> x + y; 参数类型也可以省略,Java编译器会根据上下文推断出来: (x, y) -> x + y; //返回两数之和   或者 (x, y) -> { return x + y; } //显式指明返回值 可见λ

Java8新增的Lambda表达式

Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用更简单的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例. 5.8.1 Lambda 表达式入门 Command.java package code; public interface Command { // 接口里定义的process()方法用于封装"处理行为" void process(int[] target); } ProcessArray.java package code; publi

Lambda表达式树解析(下)

概述 前面章节,总结了Lambda树的构建,那么怎么解析Lambda表达式树那?Lambda表达式是一种委托构造而成,如果能够清晰的解析Lambda表达式树,那么就能够理解Lambda表达式要传递的正式意图.解析Lambda表达式树意义很大,比如我们用的EF框架.Rafy框架,里面封装了大量的Lambda查询表达式,通过解析表达式转换成SQL语句,即可以查询数据库,将数据呈现给前台用户: Lambda表达式树解析 下面代码块是标识Express各个节点的信息,ExpressionType.Cal

Java8新特性 - Lambda表达式 - 基本知识

A lambda expression is an unnamed block of code (or an unnamed function) with a list of formal parameters and abody. Java8中的lambda表达式不同于C#,使用的是-> eg: // Takes an int parameter and returns the parameter value incremented by 1 (int x) -> x + 1 // Take

Java核心技术之Java8新特性-Lambda表达式

1 总体说明 Java8新特性概述 函数式接口 Lambda表达式(闭包) 2 Java8新特性概述 Oracle公司于2014年3月发布了Java8正式版,该版本是自JDK5.0以来最具革命性的版本. Java8为Java语言.编译器.类库和JVM带来了大量的新特性.接下来的内容将会详细说明Java8在Java语言方面的新特性以及它们的使用场景. 3 函数式接口 Java8引入的一个核心概念是函数式接口(Functional Interfaces):如果一个接口定义一个唯一的抽象方法,那么这个

JAVA8学习——深入浅出Lambda表达式(学习过程)

JAVA8学习--深入浅出Lambda表达式(学习过程) lambda表达式: 我们为什么要用lambda表达式 在JAVA中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法. 在JavaScript中,函数参数是一个函数,返回值是另一个函数的情况下非常常见的,JavaScript是一门非常典型的函数式编程语言,面向对象的语言 //如,JS中的函数作为参数 a.execute(callback(event){ event... }) Java匿名内部类实例 后面补充一个匿名内

JAVA8 Lambda表达式完全解析

JAVA8 新特性 在学习JAVA8 Lambda之前,必须先了解一下JAVA8中与Lambda相关的新特性,不然对于一些概念会感到比较陌生. 1. 接口的默认方法和静态方法 Java 8允许我们给接口添加一个默认方法,用default修饰即可.默认方法可以重写,也可以不用重写.这就是和抽象方法的区别,在用法上,没有其他区别. public interface IMyInterface { void onMethond(String str);//这是一个抽象方法 default String

【Java8实战】Lambda表达式(一)

Java 8的Lambda表达式借鉴了C#和Scala等语言中的类似特性,简化了匿名函数的表达方式.Lambda表达式可以直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例.什么是函数式接口?简单来说就是只包含一个抽象方法的接口,允许有默认的实现(使用default关键字描述方法).函数式接口建议使用@FunctionalInterface注解标注,虽然这不是必须的,但是这样做更符合规范. 在Java 8之前,实现Runnable常用方式是编写一个匿名类: Thr

java8新特性-Lambda表达式(二)

Java8新增了java.util.funcion包,里面包含常用的函数接口,这是Lambda表达式的基础,Java集合框架也新增部分接口,以便与Lambda表达式对接. Collections中的常用函数接口 Java集合框架的接口继承结构: 上图中蓝色标记和橙色标记的接口类,表示在Java8中加入了新的接口方法,由于继承关系,他们相应的子类也会继承这些方法. 下面用一张表列举这些方法 接口名 Java8新加入的方法 Collection removeIf() spliterator() st