本文章也同步至本人的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】大文本字符串滤重的简单方案~的更多相关文章

  1. JAVA里的字符串,String 类简单介绍

    http://www.360doc.com/content/14/1107/23/17130779_423471141.shtml

  2. Java查询大文本

    但JAVA本身缺少相应的类库,需要硬编码才能实现结构化文件计算,代码复杂且可读性差,难以实现高效的并行处理. 使用免费的集算器可以弥补这一不足.集算器封装了丰富的结构化文件读写和游标计算函数,书写简单 ...

  3. Java调用SqlLoader将大文本导入数据库

    Java调用SqlLoader将大文本导入数据库 业务场景:将一千万条数据,大约500M的文本文档的数据导入到数据库 分析:通过Java的IO流解析txt文本文档,拼接动态sql实现insert入库, ...

  4. <JAVA - 大作业(1)文本编辑器 >

    <JAVA - 大作业(1)文本编辑器 > 背景 JAVA上机大作业:qq / 代码评价系统 第一次上机主题是练习JAVA自带的GUI图形化编程 目的:实现一个跟window10记事本界面 ...

  5. 13、如何拆分含有多种分隔符的字符串 14、如何判断字符串a是否以字符串b开头或结尾 15、如何调整字符串中文本的格式 16、如何将多个小字符串拼接成一个大的字符串

    13.如何拆分含有多种分隔符的字符串 import re s = "23:41:2314\1234#sdf\23;" print(re.split(r'[#:\;]+',s))   ...

  6. coding++:java—提取Html文本字符串中的内容

    package com.tree.ztree_demo; import java.util.regex.Matcher; import java.util.regex.Pattern; public ...

  7. Java中的字符串操作(比较String,StringBuiler和StringBuffer)

    一.前言 刚开始学习Java时,作为只会C语言的小白,就为其中的字符串操作而感到震撼.相比之下,C语言在字节数组中保存一个结尾的\0去表示字符串,想实现字符串拼接,还需要调用strcpy库函数或者自己 ...

  8. Java中的字符串常量池

    ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...

  9. Java基础 -- 连接字符串时,使用+还是StringBuilder

    结论 1-源代码中使用的+连接,实际上都使用的是StringBuilder. 2-用jad工具反编译,好处之一就是可以同时生成字节码和源代码.这样可以进行对照研究. ----------------- ...

随机推荐

  1. MATLAB(5)——生成归一化直方图

    作者:桂. 时间:2017-03-10  22:13:36 链接:http://www.cnblogs.com/xingshansi/p/6533579.html 声明:欢迎转载,不过记得注明出处哦~ ...

  2. 从零开始学JavaWeb

    引言   记得上学时,有位导师说过一句很经典的话:"编程语言只是工具,最重要的是掌握思想." 笔者一直主要从事.net领域的开发工作.随着工作阅历的丰富,越来越深刻的理解当年导师说 ...

  3. 求取水仙花数 && 将整数分解成质因数

    [程序3] 题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身.例如: 153是一个"水仙花数", ...

  4. calling c++ from golang with swig--windows dll(一)

    calling c++ from golang with swig--windows dll 之前项目组开发的项目核心代码全部使用C++语言,新项目可能会引入golang,花了一天多时间研究了wind ...

  5. 2017年你需要一个VPN

    还有29天就2017年了,今天跟同事还在讨论这个问题,2016你都做了些什么事情?2017你有什么计划和期待?有空我们一起来聊聊,今天我们就先来聊聊VPN. 记得2016年11月初的时候,我写过一篇文 ...

  6. webots自学笔记(五)使用物理插件ODE建立铰链

    原创文章,来自"博客园,_阿龙clliu" http://www.cnblogs.com/clliu/,转载请注明原文章出处. 在一些三维制图软件或仿真软件里,都有运动副的概念,w ...

  7. idea调试SpringMvc, 出现:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener错误的解决办法

    有时,使用idea开发SpringMvc发现调试时出现以下错误: 12-Mar-2017 12:08:02.345 严重 [RMI TCP Connection(2)-127.0.0.1] org.a ...

  8. R语言数据分析利器data.table包 —— 数据框结构处理精讲

        R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理 ...

  9. go-common-pool设计原理分析

    common-pool: 对于一些对象的频繁创建会带来很大的系统开销,并且需要对对象数量进行控制来降低资源消耗,比如数据库连接,线程等 common-pool采用了缓存思想来解决这个问题,预先把一些对 ...

  10. iOS开发之UIApplication和delegate

    1.概述 所有的移动操作系统都有个致命的缺点:app很容易受到打扰.比如一个来电或者锁屏会导致app进入后台甚至被终止. 还有很多其它类似的情况会导致app受到干扰,在app受到干扰时,会产生一些系统 ...