2019做地方门户网站,免费推广网站如何提高排名,创建免费网站注意事项,网站推广120种方法目录
四、集合框架
1.集合概述
集合的作用
集合和数组的区别
集合继承体系
数组和链表
数组集合
链表集合 2.Collection
方法
集合遍历
并发修改异常
3.List
List集合的特有功能#xff08;核心是索引#xff09;
集合遍历
并发修改异常产生解决方案ListItera…目录
四、集合框架
1.集合概述
集合的作用
集合和数组的区别
集合继承体系
数组和链表
数组集合
链表集合 2.Collection
方法
集合遍历
并发修改异常
3.List
List集合的特有功能核心是索引
集合遍历
并发修改异常产生解决方案ListIterator
List的三个子类的特点
VectorArrayListLinkedList区别 4.ArrayList
5.Vector
Vector的特有功能
6.LinkedList
LinkedList类特有功能
7.Set
如何保证元素的唯一性
比较的逻辑
为什么不直接使用equals()进行比较
为什么还需要equals()
为什么重写equals()就一定要重写hashCode()
通过Set去重
8.HashSet
9.LinkedHashSet
10.TreeSet
怎么实现排序
方式一
对于compareTo()
方式二
对于compare()
11.Map
特点
Map和Collection区别
方法
Map嵌套
Map集合遍历
在类中声明Map成员时给定初始值
12.LinkedHashMap
13.TreeMap
14.HashMap
概念
数据结构
红黑树
特点
为什么需要红黑树
红黑树如何保持平衡
哈希算法
哈希函数的评价标准
哈希表
初始化
数据存储-put方法
计算hash值
计算元素存放在数组的位置
存储
哈希冲突碰撞
数据寻址-hash方法
扩容-resize方法
何时扩容
扩容过程
总结
HashMap在JDK7和8中的区别
HashMap和Hashtable的区别
HashMap线程不安全
线程不安全的体现
线程不安全的解决方案
15.ConcurrentHashMap线程安全
原理
数据结构
核心过程
其他 四、集合框架
1.集合概述
集合的作用
数组长度是固定当添加的元素超过了数组的长度时需要对数组重新定义太麻烦
因此java内部给我们提供了集合类,能存储任意对象长度是可以改变的随着元素的增加而增加随着元素的减少而减少
集合和数组的区别
元素不同
数组既可以存储基本数据类型又可以存储引用数据类型基本数据类型存储的是值引用数据类型存储的是地址值
集合只能存储引用数据类型(对象)基本数据类型在存储的时候会自动装箱变成对象
长度不同
数组长度是固定的不能自动增长
集合长度可变可以根据元素个数增减
数组和集合什么时候用
如果元素个数是固定的推荐用数组
如果元素个数不是固定的推荐用集合
集合继承体系 数组和链表
数组集合
查询快修改也快直接通过索引找到值进行修改增删慢
原因
数组一旦被初始化长度就不会被改变
初始长度是10每次add的时候 都会先判断一下 size1是否超过了数组的长度一旦超过那么就创建一个新数组长度增加int oldCapacity /2将数据复制到新数组中原数组就作废了
在某个索引位置增加时要将包括该元素的后面的每个元素都往后移动
在某个索引位置删除时要将包括该元素的后面的每个元素都向前移动被移动的最后位置置null
数组实现的集合ArrayList
链表集合
查询慢修改也慢增删快
原因
每个存储单元会记住链中前后存储单元的地址从而形成链
查询时先判断是从前还是从后找二分判断离头尾哪个近然后依次挨个存储单元找遍历
指定索引插入元素时只需要插入元素记住该索引前后单元的地址就插入成功
删除也是拿出一个元素前后索引修改记忆的前后单元的地址
链表实现的集合LinkedList 2.Collection
集合的根接口
方法
boolean add(E e) //增加
boolean remove(Object o) //删除
void clear() //清空
boolean contains(Object o) //判断是否包含
boolean isEmpty() //判断是否为空
int size() //获取元素个数
boolean addAll(Collection c) 添加所有元素
boolean removeAll(Collection c) 删除的是交集
boolean containsAll(Collection c) 判断是否包含c中的每个元素重复的也算包含
boolean retainAll(Collection c) 判断C是否包含调用者集合
集合遍历
迭代器直接遍历集合元素
Collection c new ArrayList();
c.add(a);
c.add(b);
c.add(c);
c.add(d);Iterator it c.iterator(); //获取迭代器的引用
while(it.hasNext()) { //it.hasNext()判断集合中是否仍有元素可以迭代//it.next()返回迭代的下一个元素且移动迭代器的指针到下一个元素//迭代的过程中不可以对集合的元素进行增删即不可以改变集合的结构因为迭代器无法知晓集合的结构变化会造成并发修改异常System.out.println(it.next());
}
//增强for简化数组和Collection集合的遍历底层是迭代器实现所以实际开发一般不用迭代器遍历元素
for(元素数据类型 变量 : 数组或者Collection集合) {使用变量即可该变量就是元素
}
并发修改异常
fail-fast快速失败机制并发修改异常
是Java集合的一种错误检查机制当多个线程对集合进行结构上的改变的操作时有可能会产生 fail-fast 机制注意只是有可能不是一定单线程的情况下也可能产生
多线程线程1通过Iterator在遍历集合A中的元素在某个时候线程2修改了集合A的结构这个时候程序就会抛出 ConcurrentModificationException 异常从而产生fail-fast机制
单线程在集合迭代的过程中对集合结构进行了改变增删元素
public static void main(String[] args) {ArrayListInteger arrayList new ArrayList();arrayList.add(1);arrayList.add(2);for (Integer integer : arrayList) {arrayList.add(1); //报错ConcurrentModificationException}
}
3.List
特点元素有索引有序可重复
List集合的特有功能核心是索引
void add(int index,E element) 指定索引位置添加元素
E remove(int index) 删除指定索引位置元素并返回该元素
E get(int index) 获取显然可以通过get(int index)方法遍历
E set(int index,E element) 修改
default void sort(Comparator c) 排序可以给定比较器
ListMapString, Object demoList xxMapper.getList(xx); demoList.sort(Comparator.comparingInt((Map o) - Integer.parseInt(o.get(XH).toString())));
集合遍历
通过size()和get()方法结合使用遍历
List list new ArrayList();
list.add(new Student(张三, 18));
list.add(new Student(李四, 18));
list.add(new Student(王五, 18));
list.add(new Student(赵六, 18));for(int i 0; i list.size(); i) {Student s (Student)list.get(i);System.out.println(s.getName() , s.getAge());
}
并发修改异常产生解决方案ListIterator
ListIterator lit list.listiterator()
方法
boolean hasNext()是否有下一个
boolean hasPrevious()是否有前一个
Object next()返回下一个元素
Object previous();返回上一个元素
//判断集合里面有没有world这个元素如果有添加一个javaee元素
List list new ArrayList();
list.add(a);
list.add(b);
list.add(world);
list.add(d);
list.add(e);Iterator it list.iterator();
while(it.hasNext()) {String str (String)it.next();if(str.equals(world)) {list.add(javaee);//这里会抛出ConcurrentModificationException并发修改异常原因是在迭代的时候进行了集合的增删改操作但是迭代器并不知道这会影响迭代}
}解决方案
如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
ListIterator lit list.listIterator();
while(lit.hasNext()) {String str (String)lit.next();if(str.equals(world)) {lit.add(javaee); }
}
List的三个子类的特点
ArrayList
底层数据结构是数组查询快增删慢
线程不安全效率高异步
LinkedList
底层数据结构是链表查询慢增删快
线程不安全效率高
Vector不用了
底层数据结构是数组查询快增删慢
线程安全效率低同步
VectorArrayListLinkedList区别
数据结构
ArrayListVector数组查询修改快
LinkedList链表增删快查询修改慢
线程安全
Vector线程安全效率低
ArrayListLinkedList线程不安全效率高
Vector是线程安全的,效率低 4.ArrayList
//ArrayList去重
public static ArrayList getSingle (ArrayList list){ArrayList newList new ArrayList(); //创建一个新集合Iterator it list.iterator(); //获取迭代器while (it.hasNext()) { //判断老集合中是否有元素String temp (String) it.next(); //将每一个元素临时记录住if (!newList.contains(temp)) { //如果新集合中不包含该元素newList.add(temp); //将该元素添加到新集合中}}return newList; //将新集合返回
}5.Vector
vector实现了list接口但已经被ArrayList取代了
Vector的特有功能
public void addElement(E obj)
public E elementAt(int index)
public Enumeration elements()
//Vector的迭代
Vector v new Vector();
v.addElement(a);
v.addElement(b);
v.addElement(c);
v.addElement(d); Enumeration en v.elements(); //获取枚举这不是迭代是枚举
while(en.hasMoreElements()) { //判断集合中是否有元素System.out.println(en.nextElement()); //获取集合中的元素
}
6.LinkedList
LinkedList类特有功能
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
7.Set
特点元素无索引无序指的是存放并不是按add的顺序不可重复
如何保证元素的唯一性
存入时通过对象的hashCode()和equals()比较元素已经存在的不存入Set
jdk提供的类比如基本数据类型包装类jdk已经对equals()做了重写
自定义的类也需要重写equals()给定比较的规则
比较的逻辑
在hashCode()值相同时才会进一步调用equals()进行比较否则直接认定对象不一样
为什么不直接使用equals()进行比较
因为hashCode()效率高而equals()中的操作一般都比较复杂效率较低
为什么还需要equals()
因为hashCode()是一个算法并不完全可靠当hashCode()不同则两个对象肯定不同但当hashCode()相同两个对象不一定相同采用这样的组合比较方式可以兼顾效率和可靠性
为什么重写equals()就一定要重写hashCode()
1.因为hashCode()在equals()之前调用如果不重写很可能永远调用不到equals()
2.java约定两个对象如果equals()判定相同那么hashCode()也必须判定相同
通过Set去重
public static void getSingle(ListString list) {LinkedHashSetString lhs new LinkedHashSet();lhs.addAll(list); //将list集合中的所有元素添加到lhslist.clear(); //清空原集合list.addAll(lhs); //将去除重复的元素添回到list中可以直接修改
}
8.HashSet
常用的Set子类
9.LinkedHashSet
常用的Set子类
链表结构使元素能保持有序即可以保证怎么存就怎么取存进去是a,b,c,d,取出来还是a,b,c,d
10.TreeSet
元素排序
排序的原理底层是二叉树结构
怎么实现排序
方式一
元素的类implments Comparable重写compareTo()
TreeSet类的add()方法中会把存入的对象提升为Comparable类型调用对象的compareTo()方法和集合中的对象比较根据compareTo()方法返回的结果进行存储
基本数据类型包装类默认已经实现了Comparable接口重写过compareTo()对于自定义对象可以实现Comparable接口并重写compareTo()
对于compareTo()
return 0 那么集合中只存一个元素因为每次返回0都被TreeSet认为是一样的
return 正数 那么集合中怎么存怎么取
return 负数 那么集合中倒序存储
方式二
比较器顺序(Comparator)
比较器类implments Comparator重写compare()方法将Comparator的实现类对象传给TreeeSet()对象构造方法TreeSet就会按照比较器中的顺序排序
add()方法内部会自动调用Comparator接口中compare()方法排序
对于compare()
调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数 11.Map
定义将键映射到值的对象
特点
键具有唯一性键可以是对象需要重写hashCode()和equals()保证键的唯一性
Set集合的底层是Map隐藏了值展示的是键
Map和Collection区别
Map是双列的Collection是单列的
Map子类的数据结构指的是键的数据结构比如HashMapTreeMap的Hash和Tree针对的都是键Collection集合的数据结构是针对元素有效
方法
添加
V put(K key,V value)添加元素返回的是被覆盖的值
V putIfAbsent(K key, V value)如果Map中已经有当前key不会覆盖
删除
void clear():移除所有的键值对元素
V remove(Object key)根据键删除键值对元素并把值返回
判断
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
获取
Set entrySet():获取所有键值对
V get(Object key):根据键获取值
Set keySet():获取集合中所有键的集合
Collection values():获取集合中所有值的集合
int size()返回集合中的键值对的个数
Map嵌套
Map可以嵌套即Map map new HashMap
Map集合遍历
//先拿到键根据键查找值
SetString keySet hm.keySet(); //获取集合中所有的键
IteratorString it keySet.iterator(); //获取迭代器
while(it.hasNext()) { //判断单列集合中是否有元素String key it.next(); //获取集合中的每一个元素,其实就是双列集合中的键Integer value hm.get(key); //根据键获取值System.out.println(key value); //打印键值对
}for(String key :hm.keySet()) { //增强for循环迭代双列集合第一种方式System.out.println(key hm.get(key));
}
//直接获取键值对象Map.Entry是Map的内部接口Entry将键值对封装成Entry对象存储在Set集合中
SetMap.EntryString, Integer entrySet hm.entrySet(); //获取所有的键值对象的集合
IteratorEntryString, Integer it entrySet.iterator(); //获取迭代器
while(it.hasNext()){EntryString, Integer en it.next(); //获取键值对对象String key en.getKey(); //根据键值对对象获取键Integer value en.getValue(); //根据键值对对象获取值System.out.println(key value);
}for(EntryString, Integer en :hm.entrySet()){System.out.println(en.getKey() en.getValue());
}
在类中声明Map成员时给定初始值
MapInteger, Integer map new HashMapInteger, Integer() {{put(1,0);...}
}
双花括号的含义
第一个括号是定义了一个匿名内部类
第二个括号是在这个匿名内部类中定义了一个初始化代码块
put相当于this.putthis指的是这个匿名内部类的对象本身
12.LinkedHashMap
链表结构可以保证怎么存就怎么取
13.TreeMap
键有序
统计字符串中每个字符出现的次数
String str aaaabbbcccccccccc;
char[] arr str.toCharArray(); //将字符串转换成字符数组
HashMapCharacter, Integer hm new HashMap(); //创建双列集合存储键和值for(char c : arr) { //遍历字符数组if(!hm.containsKey(c)) { //如果不包含这个键就将键和值为1添加hm.put(c, 1);}else { //如果包含这个键就将值加1添加进来hm.put(c, hm.get(c) 1);
}hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) 1);
Integer i !hm.containsKey(c) ? hm.put(c, 1) : hm.put(c, hm.get(c) 1);for (Character key : hm.keySet()) { //遍历双列集合System.out.println(key hm.get(key));
}
14.HashMap
概念
key-value 键值对的形式存放元素并封装成 Node 对象
允许使用 null 键和 null 值但只允许存在一个键为 null并且存放在 Node[0] 的位置
线程不安全采用 Fail-Fast 机制底层通过一个 modCount 值记录修改的次数对 HashMap 的修改操作都会增加这个值。迭代器在初始过程中会将这个值赋给 exceptedModCount 在迭代的过程中如果发现 modCount 和 exceptedModCount 的值不一致代表有其他线程修改了Map就立刻抛出异常
数据结构
JDK7:HashMap由 数组链表 组成
JDK8:HashMap由 数组链表红黑树 组成
红黑树
可以把红黑树简单理解为接近平衡的二叉树
特点
每个节点或者是黑色或者是红色
根节点是黑色
每个叶子节点NIL是黑色注意这里叶子节点是指为空(NIL或NULL)的叶子节点
如果一个节点是红色的则它的子节点必须是黑色的
从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点这样确保没有一条路径会比其他路径长出俩倍
为什么需要红黑树
在Java 8中如果桶数组的同一个位置上的链表数量超过TREEIFY_THRESHOLD默认是8链表会转为一棵红黑树
AVL更平衡但在频繁增删的情况下为了维持平衡会进行很多的旋转操作此时红黑树的性能更高相对的对于增删较少查询频繁的情况AVL更具优势
假如客户端实现了一个性能拙劣的hashCode方法元素较多的情况下采用红黑树可以保证HashMap的读写复杂度不会低于O(lgN)
红黑树如何保持平衡
通过旋转和重新着色
黑高bh(x)从某个结点 x 出发不包含该结点到达一个叶结点的任意一条简单路径上包含的黑色结点的数目显然黑高最多也就是h/2
哈希算法
任意长度的输入通过散列算法变换成固定长度的输出这个输出是一个地址值通过这个地址可以访问
哈希函数的评价标准
计算出来的哈希值足够散列能够有效减少哈希碰撞
本身能够快速计算得出因为HashMap每次调用get和put的时候都会调用hash方法
哈希表
根据关键码值(Key value)而直接进行访问的数据结构
通过把关键码值映射到表中一个位置来访问记录以加快查找的速度
这个映射函数叫做散列函数存放记录的数组叫做散列表
初始化
HashMap的实现的基础数据结构是数组每一对key-value的键值对组成Entity类以双向链表的形式存放到这个数组中
初始化时不会占用内存第一次put时会调用inflateTable计算bucket数组的长度开辟bucket数组占用内存
数组长度是2的整数幂初始size为16扩容newsize oldsize*2
为什么一定是2的整数幂因为这样可以通过构造位运算快速寻址定址
数据存储-put方法
计算hash值
将key-value封装成Node拿到key.hashCode()
调用hash()重新计算hash值防止拙劣hashCode()从而使hash值相对分散jdk8之后对hash()进行了优化使hashCode的高16位参与运算保证了数组较小时的hash值分散度
计算元素存放在数组的位置
将hash值与tablel.length-1进行位与运算得到元素存放位置
此处就可以理解为什么HashMap的底层数组长度总是2的n次方幂因为当 length 为2的n次方时h (length - 1) 就相当于对 length 取模而且速度比直接取模要快得多二者等价不等效这是HashMap在性能上的一个优化
存储
如果计算出的数组位置上为空那么直接将node放到该位置中
如果数组该位置上已经存在链表即有多个key的hash值通过哈希算法得到的数组下标相同即发生了哈希碰撞此时
挨个节点通过equals()对比key如果返回true则覆盖此节点如果都返回false则树形-挂到树上链表-添加到末尾Jdk1.7及以前的版本使用的头插法
如果插入元素后如果链表的节点数是否超过8个则调用 treeifyBin() 将链表节点转为红黑树节点
最后判断 HashMap 总容量是否超过阈值 threshold则调用 resize() 方法进行扩容扩容后数组的长度变成原来的2倍
哈希冲突碰撞
通过hash计算出的hash值相同继而导致存放位置相同即为hash冲突
hashMap的处理方式是拉链法即将所有hash值相同的元素放在同一个链表中
数据寻址-hash方法
先调用k的hashCode()方法得出哈希值并通过hash()算法转换成数组的下标
通过数组下标快速定位到某个位置上
如果这个位置上什么都没有则返回null
如果这个位置上有链表那么它就会拿着K和链表上的每一个Node的K进行equals()
如果所有equals方法都返回false则get方法返回null
如果其中一个节点的K和参数K进行equals返回true那么此时该节点的value就是我们要找的value了get方法最终返回这个要找的value
扩容-resize方法
为什么需要扩容减少哈希碰撞从而减小链表长度/树高让value分配更均匀从而提升读取效率
何时扩容
HashMap 有两个影响性能的关键参数初始容量加载因子
容量 capacity就是哈希表中数组的数量默认初始容量是16容量必须是2的N次幂
加载因子 loadfactor在 HashMap 扩容之前容量可以达到多满的程度默认值为 0.75
扩容阈值 threshold capacity * loadfactor
扩容形式扩容针对整个Map每次扩容时原来数组中的元素依次重新计算存放位置并重新插入如果扩容两倍则有一半的节点需要存到扩容的部分中
扩容过程
重新建立一个新的数组长度为原数组的两倍
遍历旧数组的每个数据重新计算每个元素在新数组中的存储位置。使用节点的hash值与旧数组长度进行位与运算如果运算结果为0表示元素在新数组中的位置不变否则则在新数组中的位置下标原位置原数组长度
将旧数组上的每个数据使用尾插法逐个转移到新数组中并重新设置扩容阈值
为什么扩容时节点重 hash 只可能分布在原索引位置或者 原索引长度oldCap 位置由确定存址的位运算特征决定的
总结
为何随机增删、查询效率都很高增删是在链表上完成的而查询只需扫描部分则效率高
HashMap在JDK7和8中的区别
①数据结构
JDK7及之前的版本数组链表
JDK8及之后的版本数组链表红黑树当链表的长度超过8时链表就会转换成红黑树从而降低时间复杂度由O(n) 变成了 O(logN)
②对数据重哈希
JDK8 及之后的版本对 hash() 方法进行了优化重新计算 hash 值时让 hashCode 的高16位参与异或运算目的是在 table 的 length较小的时候在进行计算元素存储位置时也让高位也参与运算
③插入元素的方式
在 JDK7 及之前的版本在添加元素的时候采用头插法所以在扩容的时候会导致之前元素相对位置倒置了在多线程环境下扩容可能造成环形链表而导致死循环的问题
DK1.8之后使用的是尾插法扩容是不会改变元素的相对位置
④扩容时重新计算元素的存储位置的方式
JDK7 及之前的版本重新计算存储位置是直接使用 hash (table.length-1)
JDK8 使用节点的hash值与旧数组长度进行位与运算如果运算结果为0表示元素在新数组中的位置不变否则则在新数组中的位置下标原位置原数组长度
⑤扩容决策不同
JDK7 是先扩容后插入这就导致无论这次插入是否发生hash冲突都需要进行扩容但如果这次插入并没有发生Hash冲突的话那么就会造成一次无效扩容
JDK8是先插入再扩容的优点是减少这一次无效的扩容原因就是如果这次插入没有发生Hash冲突的话那么其实就不会造成扩容
HashMap和Hashtable的区别
线程安全
HashMap线程不安全效率高
HashTable线程安全效率低
null键值
HashMap可以存储null键和null值
HashTable不可以存储null键和null值
数据结构
HashMap使用数组链表红黑树
HashTable使用数组链表
初始容量和扩容方式
HashMap默认初始容量为16每次扩容为原来的2倍
HashTable默认初始容量为11每次扩容为原来的2倍1
元素的Hash值
HashMap会重计算
HashTable直接使用object.hashCode()
继承的父类
HashMap继承自AbstractMap类
HashTable继承自Dictionary类
HashMap线程不安全
线程不安全的体现
头插法导致同一位置节点顺序相反导致出现死循环
多线程操作HashMap插入元素数据可能丢失
线程不安全的解决方案
使用HashTable
使用Collections.synchronizedMap()方法来获取一个线程安全的集合底层原理是使用synchronized来保证线程同步
使用ConcurrentHashMap 15.ConcurrentHashMap线程安全
原理
JDK8相比JDK7抛弃了 JDK7 版本的 Segment分段锁的概念而是采用了 synchronized CAS 算法来保证线程安全可以大大减少使用加锁造成的性能消耗
JDK7中ConcurrentHashMap使用分段锁机制数据结构可以看成是Segment锁Entry数组链表一个ConcurrentHashMap实例中包含若干个Segment实例组成的数组每个Segment实例又包含由若干个桶每个桶中都是由若干个HashEntry对象链接起来的链表
JDK8 降低了锁的粒度采用table数组元素作为锁从而实现对每行数据进行加锁进一步减少并发冲突的概率并使用synchronized来代替ReentrantLock因为在低粒度的加锁方式中synchronized并不比ReentrantLock差在粗粒度加锁中ReentrantLock可以通过Condition来控制各个低粒度的边界更加的灵活而在低粒度中Condition的优势就没有了
数据结构
JDK7Segment数组HashEntry数组链表
JDK8HashEntry数组链表红黑树
核心过程
存储时对key进行重哈希通过segmentFor()计算出元素属于哪个Segment插入前使用lock()进行加锁之后使用头插法插入元素锁是基于Segment其他插入操作只要Segment没有被锁不受影响
插入元素之前会检测本次操作会不会超过Segment元素数量超过扩容阈值超过则执行扩容操作后再插入
其他
size()
JDK7ConCurrentHashMap没有使用全局计数器而是给每个Segment定义自己的计数器执行size()时先尝试不对Segment加锁统计如果统计过程中元素个数发生了变化再对所有的Segment加锁统计
JDK8扩容和addCount()中先行处理等到调用size()时直接返回元素的个数 文章转载自: http://www.morning.tpqrc.cn.gov.cn.tpqrc.cn http://www.morning.4r5w91.cn.gov.cn.4r5w91.cn http://www.morning.pflry.cn.gov.cn.pflry.cn http://www.morning.gxhqt.cn.gov.cn.gxhqt.cn http://www.morning.wmfmj.cn.gov.cn.wmfmj.cn http://www.morning.rjrlx.cn.gov.cn.rjrlx.cn http://www.morning.ngkgy.cn.gov.cn.ngkgy.cn http://www.morning.qgmwt.cn.gov.cn.qgmwt.cn http://www.morning.zrdhd.cn.gov.cn.zrdhd.cn http://www.morning.sxcwc.cn.gov.cn.sxcwc.cn http://www.morning.grxbw.cn.gov.cn.grxbw.cn http://www.morning.jjzjn.cn.gov.cn.jjzjn.cn http://www.morning.qrzqd.cn.gov.cn.qrzqd.cn http://www.morning.pjfmq.cn.gov.cn.pjfmq.cn http://www.morning.skfkx.cn.gov.cn.skfkx.cn http://www.morning.tgmfg.cn.gov.cn.tgmfg.cn http://www.morning.rwls.cn.gov.cn.rwls.cn http://www.morning.nldsd.cn.gov.cn.nldsd.cn http://www.morning.rksnk.cn.gov.cn.rksnk.cn http://www.morning.ypcd.cn.gov.cn.ypcd.cn http://www.morning.tfpqd.cn.gov.cn.tfpqd.cn http://www.morning.kwdfn.cn.gov.cn.kwdfn.cn http://www.morning.rbbzn.cn.gov.cn.rbbzn.cn http://www.morning.bxfy.cn.gov.cn.bxfy.cn http://www.morning.jgcrr.cn.gov.cn.jgcrr.cn http://www.morning.jcfdk.cn.gov.cn.jcfdk.cn http://www.morning.rqknq.cn.gov.cn.rqknq.cn http://www.morning.tymnr.cn.gov.cn.tymnr.cn http://www.morning.qrsm.cn.gov.cn.qrsm.cn http://www.morning.tcxzn.cn.gov.cn.tcxzn.cn http://www.morning.rgtp.cn.gov.cn.rgtp.cn http://www.morning.hcrxn.cn.gov.cn.hcrxn.cn http://www.morning.jzfrl.cn.gov.cn.jzfrl.cn http://www.morning.srwny.cn.gov.cn.srwny.cn http://www.morning.yxnfd.cn.gov.cn.yxnfd.cn http://www.morning.xfwnk.cn.gov.cn.xfwnk.cn http://www.morning.ksggr.cn.gov.cn.ksggr.cn http://www.morning.tpyrn.cn.gov.cn.tpyrn.cn http://www.morning.vnuwdy.cn.gov.cn.vnuwdy.cn http://www.morning.yfnjk.cn.gov.cn.yfnjk.cn http://www.morning.rhdln.cn.gov.cn.rhdln.cn http://www.morning.wtcd.cn.gov.cn.wtcd.cn http://www.morning.hwcgg.cn.gov.cn.hwcgg.cn http://www.morning.khtjn.cn.gov.cn.khtjn.cn http://www.morning.rwpfb.cn.gov.cn.rwpfb.cn http://www.morning.mqdr.cn.gov.cn.mqdr.cn http://www.morning.bxbkq.cn.gov.cn.bxbkq.cn http://www.morning.btgxf.cn.gov.cn.btgxf.cn http://www.morning.tdzxy.cn.gov.cn.tdzxy.cn http://www.morning.wrtsm.cn.gov.cn.wrtsm.cn http://www.morning.klrpm.cn.gov.cn.klrpm.cn http://www.morning.lzdbb.cn.gov.cn.lzdbb.cn http://www.morning.bchfp.cn.gov.cn.bchfp.cn http://www.morning.ftntr.cn.gov.cn.ftntr.cn http://www.morning.hnhgb.cn.gov.cn.hnhgb.cn http://www.morning.fdfsh.cn.gov.cn.fdfsh.cn http://www.morning.sskns.cn.gov.cn.sskns.cn http://www.morning.zbgqt.cn.gov.cn.zbgqt.cn http://www.morning.yggdq.cn.gov.cn.yggdq.cn http://www.morning.gcrlb.cn.gov.cn.gcrlb.cn http://www.morning.qfqld.cn.gov.cn.qfqld.cn http://www.morning.pqfbk.cn.gov.cn.pqfbk.cn http://www.morning.gkjyg.cn.gov.cn.gkjyg.cn http://www.morning.cbczs.cn.gov.cn.cbczs.cn http://www.morning.wjlkz.cn.gov.cn.wjlkz.cn http://www.morning.pjqxk.cn.gov.cn.pjqxk.cn http://www.morning.njhyk.cn.gov.cn.njhyk.cn http://www.morning.mkfhx.cn.gov.cn.mkfhx.cn http://www.morning.tzmjc.cn.gov.cn.tzmjc.cn http://www.morning.npmpn.cn.gov.cn.npmpn.cn http://www.morning.krdxz.cn.gov.cn.krdxz.cn http://www.morning.lxhrq.cn.gov.cn.lxhrq.cn http://www.morning.srwny.cn.gov.cn.srwny.cn http://www.morning.jrslj.cn.gov.cn.jrslj.cn http://www.morning.bloao.com.gov.cn.bloao.com http://www.morning.qzmnr.cn.gov.cn.qzmnr.cn http://www.morning.hwsgk.cn.gov.cn.hwsgk.cn http://www.morning.muzishu.com.gov.cn.muzishu.com http://www.morning.gqddl.cn.gov.cn.gqddl.cn http://www.morning.mhsmj.cn.gov.cn.mhsmj.cn