写在前边的实现需求:

1.总共10万个电话号码;

2.电话号码中有重复和错误;

3.查找出正确的号码(不重复);

一、优化前的实现方式:

1.先用正则过滤一遍10万条数据,找出错误的;

2.用List.Contains验证重复数据,List.Add添加不重复数据;

3.最终从List中取出正确的数据。

 public class appMain {
final static int _capacity = 1000000;
final static Random rand = new Random(System.currentTimeMillis() + _capacity);
static ArrayList<String> list = new ArrayList<String>(_capacity);
static ArrayList<String> newlist = new ArrayList<String>(_capacity); public static void main(String[] args) throws InterruptedException {
long ts = System.currentTimeMillis();
int modVal = _capacity / 3;
for (int i = 0; i < _capacity; i++) {
rand.setSeed(i);
list.add(Integer.toString(Math.abs(rand.nextInt() % modVal)));
}
ts = System.currentTimeMillis() - ts;
System.out.println("生成时间 :" + ts); test1();
} static void test1() {
newlist.clear();
int repetition = 0;
long ts = System.currentTimeMillis();
for (String s : list) {
if (!newlist.contains(s))
newlist.add(s);
else {
repetition++;
}
}
ts = System.currentTimeMillis() - ts;
System.out.println("------ 插入检查方法 -------");
System.out.println("查找时间 :" + ts);
System.out.println("重复 :" + repetition);
System.out.println("正确 :" + newlist.size());
}
}

优化前执行结果:

/*
条件:capacity = 100000
结果:
生成时间 :33
------ 插入检查方法 -------
查找时间 :6612
重复 :76871
正确 :23129
------ 排序检查方法 -------
查找时间 :91
重复 :76871
正确 :23129
*/

使用以上方式做导入的话数据量一旦超过5w以上马上出现假死状态,故肯定不可取,所以有了下边的优化。

二、优化后的实现方式:

1.先对10万数据排序;

2.对比前后两条数据(这个我之后会详细说明为什么这么做);

3.筛选出正确数据。

 public class appMain {
final static int _capacity = 1000000;
final static Random rand = new Random(System.currentTimeMillis() + _capacity);
static ArrayList<String> list = new ArrayList<String>(_capacity);
static ArrayList<String> newlist = new ArrayList<String>(_capacity); public static void main(String[] args) throws InterruptedException {
long ts = System.currentTimeMillis();
int modVal = _capacity / 3;
for (int i = 0; i < _capacity; i++) {
rand.setSeed(i);
list.add(Integer.toString(Math.abs(rand.nextInt() % modVal)));
}
ts = System.currentTimeMillis() - ts;
System.out.println("生成时间 :" + ts); test2();
} static void test2() {
newlist.clear();
int repetition = 0;
long ts = System.currentTimeMillis(); Collections.sort(list);
String str = list.get(0);
int max = list.size();
for (int i = 1; i < max; i++) {
if (str.equals(list.get(i))) {
repetition++;
continue;
}
newlist.add(str);
str = list.get(i);
}
newlist.add(str); ts = System.currentTimeMillis() - ts;
System.out.println("------ 排序检查方法 -------");
System.out.println("查找时间 :" + ts);
System.out.println("重复 :" + repetition);
System.out.println("正确 :" + newlist.size());
}
}

优化后执行结果:

/*
条件:capacity = 1000000
结果:
生成时间 :392
------ 插入检查方法 -------
查找时间 :1033818
重复 :703036
正确 :296964
------ 排序检查方法 -------
查找时间 :1367
重复 :703036
正确 :296964
*/

当数据量达到10万条的时候,查找时间比差不多90倍的差距了;当数据量达到100万时,我这边测试数据已经卡死在test1(),而test2()依然能在数十秒内反馈结果。

下边来简单解剖下源码:

 Collections.sort(list);
String str = list.get(0);
int max = list.size();
for (int i = 1; i < max; i++) {
if (str.equals(list.get(i))) {
repetition++;
continue;
}
newlist.add(str);
str = list.get(i);
}

Line 1:排序,加入list排序后的结果是[1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]

Line 2:初始str = 1;

从Line 4开始进入循环:

Line 5:判断str是否和当先selector值相等(暂借我们认为list.get(i)是一个指针),如果相等则跳过以下步骤进入下一个循环

Line 9:将str = 1,加入newlist尾

Line10:将当前selector值赋给str,此时str=2,进入下一个循环

...

这种语言解释我个人觉得特别麻烦,我还是写段代码让程序告诉你它怎么执行的。

 public class appList {
static ArrayList<String> list = new ArrayList<String>();
static ArrayList<String> newlist = new ArrayList<String>(); public static void main(String[] args) {
for (int i = 1; i < 5 + 1; i++) {
for (int j = 0; j < i; j++) {
list.add(Integer.toString(i));
}
}
System.out.println("list初始值 " + list.toString());
// print输出值 [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5] String str = list.get(0);
int max = list.size();
for (int i = 1; i < max; i++) {
Print(i);
if (str.equals(list.get(i))) {
PrintNew();
continue;
}
newlist.add(str);
System.out.println("add\t" + str);
str = list.get(i);
PrintNew();
} newlist.add(str);
System.out.println("add\t" + str);
PrintNew(); System.out.println("newlist值 " + newlist.toString());
// print输出值 [1, 2, 3, 4, 5]
} static void PrintNew(){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("newlist\t");
for (int i = 0; i < newlist.size(); i++) {
stringBuilder.append(newlist.get(i));
stringBuilder.append(",");
}
System.out.println(stringBuilder.toString());
System.out.println();
}
static void Print(int pos) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("list\t");
for (int i = 0; i < list.size(); i++) {
if (i == pos) {
stringBuilder.append("[");
stringBuilder.append(list.get(i));
stringBuilder.append("],");
} else {
stringBuilder.append(list.get(i));
stringBuilder.append(",");
}
}
System.out.println(stringBuilder.toString());
}

执行结果:

list初始值 [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]
list 1,[2],2,3,3,3,4,4,4,4,5,5,5,5,5,
add 1
newlist 1, list 1,2,[2],3,3,3,4,4,4,4,5,5,5,5,5,
newlist 1, list 1,2,2,[3],3,3,4,4,4,4,5,5,5,5,5,
add 2
newlist 1,2, list 1,2,2,3,[3],3,4,4,4,4,5,5,5,5,5,
newlist 1,2, list 1,2,2,3,3,[3],4,4,4,4,5,5,5,5,5,
newlist 1,2, list 1,2,2,3,3,3,[4],4,4,4,5,5,5,5,5,
add 3
newlist 1,2,3, list 1,2,2,3,3,3,4,[4],4,4,5,5,5,5,5,
newlist 1,2,3, list 1,2,2,3,3,3,4,4,[4],4,5,5,5,5,5,
newlist 1,2,3, list 1,2,2,3,3,3,4,4,4,[4],5,5,5,5,5,
newlist 1,2,3, list 1,2,2,3,3,3,4,4,4,4,[5],5,5,5,5,
add 4
newlist 1,2,3,4, list 1,2,2,3,3,3,4,4,4,4,5,[5],5,5,5,
newlist 1,2,3,4, list 1,2,2,3,3,3,4,4,4,4,5,5,[5],5,5,
newlist 1,2,3,4, list 1,2,2,3,3,3,4,4,4,4,5,5,5,[5],5,
newlist 1,2,3,4, list 1,2,2,3,3,3,4,4,4,4,5,5,5,5,[5],
newlist 1,2,3,4, add 5
newlist 1,2,3,4,5, newlist值 [1, 2, 3, 4, 5]

最新文章

  1. shared_ptr 线程安全
  2. Effective C++ 之 0 导读(Introduction)
  3. MBR中“起始磁头/扇区/柱面“同&quot;逻辑区块地址(LBA)&quot;的区别
  4. 《Linux内核设计与实现》读书笔记(七)- 中断处理【转】
  5. linux 查看某一端口的占用情况
  6. 内存映射文件详解-----C++实现
  7. jquery 的attr()方法解析
  8. ColumnEdit 数据源修改
  9. Jquery弹出窗口
  10. Docker Daemon 参数最佳实践
  11. BZOJ2338: [HNOI2011]数矩形
  12. jQuery.extend 函数使用详解
  13. Java面向对象(二、继承)
  14. bzoj3769 spoj 8549 BST again
  15. C# 获取 mp3文件信息【包括:文件大小、歌曲长度、歌手、专辑】
  16. H264视频压缩算法
  17. TCP/IP 笔记 - 用户数据报协议和IP分片
  18. 从零系列--开发npm包(二)
  19. uploadify IE11 不兼容问题(不显示图片)
  20. forkcms 开启调试模式

热门文章

  1. echarts图标legend全选功能添加
  2. HTML5应用——生日快乐动画之星星
  3. Spring IOC机制使用SpEL
  4. 14.Diameter of Binary Tree(二叉树的直径)
  5. 利用Android studio开发Java工程
  6. maven 过滤webapp下的文件
  7. chkconfig命令详细介绍
  8. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_方法执行
  9. newFixedThreadPool固定线程使用
  10. django 请求体和请求体相关知识