【Java】大文本字符串滤重的简单方案~
本文章也同步至本人的CSDN博客中: http://blog.csdn.net/u012881584/article/details/70477832
今天来说一个Java中处理大文本字符串虑重的两个解决方案。
相信大家在实际工作中都遇到过数据重复的问题, 当然也就存在虑重的工作。
比如数据库中需要对同一个字段进行虑重, 大多数情况下我们直接使用Set就能解决问题, 今天我所说的这个大文本虑重是什么含义呢?一起来看看需求吧。
需求:
公司SEO人员给了我一个文本文件, 里面大概有三千多万行字符串, 他们的要求是希望我用最短的时间把这个文本文件重复的给删除掉。 起初我想的直接用excle去处理吧, 当时 因为这个文件都达到了几百兆, 所以编辑修改起来都很费劲。
这里直接給出解决思路:
首先脑海中想到的第一个就是用大数据去处理, 只是耳边经常听过Hadoop,Spark之类的词, 但是自己也并未真正接触过。于是便一通Google, 然后找到两个解决方案。
- 利用布隆过滤器去解决。
- 利用Spark的distinct去解决。
1, 布隆过滤器
- 原理
如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定。链表、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路。但是随着集合中元素的增加,我们需要的存储空间越来越大。同时检索速度也越来越慢。
Bloom Filter 是一种空间效率很高的随机数据结构,Bloom filter 可以看做是对 bit-map 的扩展, 它的原理是:
当一个元素被加入集合时,通过 K 个 Hash 函数将这个元素映射成一个位阵列(Bit array)中的 K 个点,把它们置为 1。检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它了:
如果这些点有任何一个 0,则被检索元素一定不在;
如果都是 1,则被检索元素很可能在。
优点
It tells us that the element either definitely is not in the set or may be in the set.
它的优点是空间效率和查询时间都远远超过一般的算法,布隆过滤器存储空间和插入 / 查询时间都是常数O(k)。另外, 散列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。缺点
但是布隆过滤器的缺点和优点一样明显。误算率是其中之一。随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表足矣。
(误判补救方法是:再建立一个小的白名单,存储那些可能被误判的信息。)
另外,一般情况下不能从布隆过滤器中删除元素. 我们很容易想到把位数组变成整数数组,每插入一个元素相应的计数器加 1, 这样删除元素时将计数器减掉就可以了。然而要保证安全地删除元素并非如此简单。首先我们必须保证删除的元素的确在布隆过滤器里面. 这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。
这里只是简单做个介绍, 有兴趣的盆友可以参考:更多布隆过滤器简介。
- 代码示例:
public static void main(String[] args) throws Exception {
final BloomFilter<String> dealIdBloomFilter = BloomFilter.create(new Funnel<String>() {
@Override
public void funnel(String from, PrimitiveSink into) {
into.putString(from, Charsets.UTF_8);
}
//0.0000001d为错误率, 9000000 为预估元素的个数, 我第一次测试用了大概9000000行字符串的文本
}, 9000000, 0.0000001d);
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("C:\\Users\\WangMeng\\Desktop\\test.txt")), "utf-8"));
String line;
int i = 0;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
final boolean put = dealIdBloomFilter.put(line);
if (put) {
sb.append(line).append("\n");
i++;
}
if (i % 1000 == 0) {
//保存虑重后的文本。
FileUtils.write(new File("C:\\Users\\WangMeng\\Desktop\\Java类\\seo\\bloomFilterSplit.txt"),
sb.toString(), Charsets.UTF_8, true);
sb = new StringBuilder();
}
}
}
使用BloomFilter,有三个重要的值,错误率(false positive rate)、哈希函数个数以及BloomFilter位数组的大小,关于这三个值的最优配置算法,相关阅读中的文章有详细的说明。有一个原则,(BloomFilter位数组大小)/(实际的元素个数)越大,错误率越低,但消耗的空间会越多.
2, 使用Spark过滤大文本文件
使用或者说接触Spark是因为公司有人做过一次这个方面的分享, 所以有些耳熟, 于是便从网上找了些入门按理, 自己尝试着用了一下。
- 使用Spark首先需要在pom文件中引入spark-core包
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-core_2.11 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.1.0</version>
</dependency>
public static void main(String[] args) throws Exception {
System.setProperty("hadoop.home.dir", "C:\\Users\\WangMeng\\Desktop\\Java类\\hadoop-common-2.2.0\\");
SparkConf conf = new SparkConf().setAppName("Text String Distinct").setMaster("local").set("spark.executor.memory", "1g");
JavaSparkContext sc = new JavaSparkContext(conf);
//读取需要虑重的文本文件
JavaRDD<String> textFile = sc.textFile("C:\\Users\\WangMeng\\Desktop\\Java类\\seo\\test.txt");
final JavaRDD<String> distinct = textFile.distinct();
final long count = distinct.count();
//保存率重后的文本文件
distinct.coalesce(1).saveAsTextFile("C:\\Users\\WangMeng\\Desktop\\Java类\\seo\\sparkSplit.txt");
}
用Spark是不是很简单?代码也很少, 只需要读取文本创建一个rdd, 然后使用distinct就可以了, 如果想了解更多可以查看:Spark更多介绍。
在windows下这里好像好需要一个hadoop-common-2.2.0包, 如果不引入会报找不到winutils.exe, 这里提供一个下载地址, 如果不能下载了请联系我。hadoop-common-2.2.0下载地址
结语
到了这里就讲完了, 当然, 对于大文本的处理还是有更多更好的方法的,我这里只是尝试了这两种方案, 处理千万级行的数据都不用一分钟就可以虑重好, 布隆过滤器和Spark过滤后的行数都是相差无几的, 这里我还是更推荐使用Spark, 毕竟现在比较流行大数据, 有时间我也会继续探究大数据的相关内容。
【Java】大文本字符串滤重的简单方案~的更多相关文章
- JAVA里的字符串,String 类简单介绍
http://www.360doc.com/content/14/1107/23/17130779_423471141.shtml
- Java查询大文本
但JAVA本身缺少相应的类库,需要硬编码才能实现结构化文件计算,代码复杂且可读性差,难以实现高效的并行处理. 使用免费的集算器可以弥补这一不足.集算器封装了丰富的结构化文件读写和游标计算函数,书写简单 ...
- Java调用SqlLoader将大文本导入数据库
Java调用SqlLoader将大文本导入数据库 业务场景:将一千万条数据,大约500M的文本文档的数据导入到数据库 分析:通过Java的IO流解析txt文本文档,拼接动态sql实现insert入库, ...
- <JAVA - 大作业(1)文本编辑器 >
<JAVA - 大作业(1)文本编辑器 > 背景 JAVA上机大作业:qq / 代码评价系统 第一次上机主题是练习JAVA自带的GUI图形化编程 目的:实现一个跟window10记事本界面 ...
- 13、如何拆分含有多种分隔符的字符串 14、如何判断字符串a是否以字符串b开头或结尾 15、如何调整字符串中文本的格式 16、如何将多个小字符串拼接成一个大的字符串
13.如何拆分含有多种分隔符的字符串 import re s = "23:41:2314\1234#sdf\23;" print(re.split(r'[#:\;]+',s)) ...
- coding++:java—提取Html文本字符串中的内容
package com.tree.ztree_demo; import java.util.regex.Matcher; import java.util.regex.Pattern; public ...
- Java中的字符串操作(比较String,StringBuiler和StringBuffer)
一.前言 刚开始学习Java时,作为只会C语言的小白,就为其中的字符串操作而感到震撼.相比之下,C语言在字节数组中保存一个结尾的\0去表示字符串,想实现字符串拼接,还需要调用strcpy库函数或者自己 ...
- Java中的字符串常量池
ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...
- Java基础 -- 连接字符串时,使用+还是StringBuilder
结论 1-源代码中使用的+连接,实际上都使用的是StringBuilder. 2-用jad工具反编译,好处之一就是可以同时生成字节码和源代码.这样可以进行对照研究. ----------------- ...
随机推荐
- 或许是介绍Android Studio使用Git最详细的文章
欢迎访问我的个人博客转发请注明出处:http://www.wensibo.top/2017/03/12/GitOnAS/ 前言 本文较长,图片很多很多,流量党慎入 使用Git已经有一段时间了,但是之前 ...
- DotNet友元程序集解析
项目开发的过程中,调试使用的可能是最多的操作.任何代码写出来都需要经过调试和整合,以此扩展和提升程序的稳定性和可靠性.谈到.NET的单元测试,在这里就得提提.NET的友元程序集这一特性,也借用.NET ...
- H5 拖放
HTML 5 拖放 HTML5 音频 HTML5 画布 拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中, ...
- C#(.Net)知识点记录
一:批量插入"SqlBulkCopy"的应用 PS:"SqlBulkCopy"的官方释义:"Lets you efficiently bulk loa ...
- Spring 4 支持的 Java 8 特性
Spring 框架 4 支持 Java 8 语言和 API 功能.在本文中,我们将重点放在 Spring 4 支持新的 Java 8 的功能.最重要的是 Lambda 表达式,方法引用,JSR-310 ...
- 图解Javascript——作用域、作用域链、闭包
什么是作用域? 作用域是一种规则,在代码编译阶段就确定了,规定了变量与函数的可被访问的范围.全局变量拥有全局作用域,局部变量则拥有局部作用域. js是一种没有块级作用域的语言(包括if.for等语句的 ...
- (28)初识struts框架
案例剖析中介绍了一个自己写的mystruts框架,这里开始简单的认识struts框架. 1.先看一个简单的struts开发的例子来熟悉一下流程 Struts就是基于mvc模式的框架! (struts其 ...
- 使用Hibernate中出现了Caused by: java.sql.SQLException: Field 'gid' doesn't have a default value
那是因为表中没有设置主键自动增长,只需要改变表中的主键设置为自动增长即可
- 分享几个不错的Android开源音视频播放器
整理了一下Github上几个开源的音视频播放器项目,有兴趣的同学可以clone代码去研究学习. UniversalMusicPlayer https://github.com/googlesamp ...
- SSH里面使用jQuery的ajax
今天我真的很兴奋!在我的SSH项目中用jQuery的异步传输成功了,经过一天多的奋战,大工告成! 我的项目需求是在javascript中向我的controller(即:action)中传输form表单 ...