集合框架图
为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,
集合就是存储对象最常用的一种方式
数组和集合类同是容器,有何不同?
数组虽然可以存储对象,但长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象。
集和类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式都有不同。
这个存储方式称之为:数据结构
一、Colllection --- 集合类的超级接口
Collection
|--List:元素是有序的,元素可以重复。因为该集合体系有索引|--Set:元素是无序的,元素不可以重复
1.添加
boolean add(Object); 参数类型是Object,以便于接收任意类型的对象,集合中存储都是对象的引用
boolean addAll(Collection); //添加一组数据
注意:
1)参数类型是Object,以便于接收任意类型的对象
2)集合中存储都是对象的引用
2.获取集合长度,即元素个数
int size(); 获取数组长度
3.删除元素
boolean remove(Object);
boolean removeAll(Collection); 删除该集合中包含另一集合中的元素,A-B
retainAll(Collection); 取交集,保留两个集合共有的元素
void clear(); 清空集合
4.判断元素
boolean contains(Object);判断是否存在某个元素
boolean containsAll(Collection);判断是否包含另一集合中的所有元素
boolean isEmpty(); 判断集合是否为空,实际上是判断集合的size是否为0
5. Iterator iterator();
返回在此 collection 的元素上进行迭代的迭代器
6.集合转变成数组
Object[] toArray();
T[] toArray(T[]);
二、迭代器----Iterator
其实就是集合的取出元素的方式
对于集合的元素取出这个动作:
当不足以用一个函数来描述,需要用多个功能来体现,所以就将取出这个动作封装成一个对象来描述。就把取出方式定义在集合
的内部,这样取出方式就可以直接访问集合内部的元素。那么取出方式就被定义成了内部类。
而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都有共性内容判断和取出。那么就可以将这些共性抽取。这些内部类都符合一个规则,该规则就是Iterator。通过一个对外提供的方法 iterator();,可以获取集合的取出对象。
Iterator类的常用操作
boolean hasNext();判断是否还有元素
E next();取出元素。
注意:没有指定泛型的情况下返回的Object对象,必须进行强制类型转换
void remove();移除元素
取出元素的时候要注意用hasNext();判断是否还有元素,如果在没有元素的情况下调用next()会抛出没有元素可以迭代的异常----NoSuchElementException。所以在进行迭代操作的时候通常会搭配hasNext()方法来使用
示例代码:
public class CollectionDemo {
public static void main(String[] args) {
Collection coll = new ArrayList();
//添加元素
coll.add("hello");
coll.add("jei");
coll.add("heihei");
//迭代输出
//方式一
Iterator iter = coll.iterator();
while(iter.hasNext()){
System.out.println("iter:"+iter.next());
}
//方式二
for(Iterator iter2=coll.iterator() ; iter2.hasNext();){
if("heihei".equals((String)iter2.next()))
//用迭代器删除元素
iter2.remove();
}
System.out.println(coll);
}
}
三、List集合
List
|--ArrayList 底层数据结构用的是数组。特点:查询速度很快,但是增删稍慢。线程不同步
|--LinkedList 底层数据结构用的是链表结构。特点:增删速度很块,查询稍慢
|--Vector 底层数据结构是数组。特点:线程同步,但是增删改查速度都相对较慢,被ArrayList替代
注:List中用来判断重复的是equals方法
1.List特有的方法
1)增
add(index,element);指定位置添加元素
addAll(index,Collection);指定位置添加指定集合中所有元素
2)删
remove(index);删除指定位置的元素
3)改
set(index,element);修改指定位置的元素
4)查
get(index); 获取指定位置的元素
sublist(fromIndex,toIndex);获取部分元素,包含头,不包含尾
5)其他方法
indexOf(Object); 获取元素第一次出现的位置
lastIndexOf(Object); 反向索引
ListIterator listIterator(); 返回List特有的迭代器
ListIterator listIterator(index); 返回List特有的迭代器,从列表的指定位置开始
2.ListIterator
ListIterator是List集合特有的迭代器,是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以在迭代器时,只能用迭代器的方法操作元素。可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。该接口只能通过List集合的ListIterator方法获取。
ListIterator特有的方法
add(obj); 在当前元素之后增加一个元素
set(obj); 将当前元素修改为obj
hasPrevious(); 判断前面有没有元素
previous(); 取前一个元素
注:Listerator可以双向迭代,但是要先向后迭代,才能向前迭代
3.枚举-----Enumeration
枚举就是Vector特有的取出方式
其实枚举和迭代是一样的,因为枚举的名称以及方法都名称都过长,所以被迭代器取代了。
枚举特有方法
hasMoreElements(); 是否还有更多元素
nextElement(); 取下一个元素
示例代码:
Vector vector = new Vector();
vector.add("java01");
vector.add("java02");
vector.add("java03");
for(Enumeration enumeration = vector.elements();enumeration.hasMoreElements();)
System.out.println("enumeration:"+enumeration.nextElement());
4.LinkedList
LinkedList特有的方法
1)增加
addFirst(); 在集合头部增加元素
addLast(); 在集合尾部增加元素
2)获取
getFirst() 获取集合中第一个元素,集合为空时会抛出NoSuchElementException
getLast(); 获取集合中最后一个元素,集合为空时会抛出NoSuchElementException
3)删除
removeFirst(); 移除集合中第一个元素,集合为空时会抛出NoSuchElementException
removeLast(); 移除集合中第一个元素,集合为空时会抛出NoSuchElementException
示例代码:
LinkedList ll = new LinkedList();
//在集合头部增加元素
ll.addFirst("java01");
ll.addFirst("java02");
ll.addFirst("java03");
System.out.println(ll);
//获取集合中最后一个元素
System.out.println("the last element in LinkedList is :"+ll.getLast());
//删除集合中第一个元素
ll.removeFirst();
System.out.println("after removeFirst: "+ll);
运行截图:
在JDK1.6以后,出现了替代方法。
1)增
offerFirst();
offerLast();
2)获取
获取元素,但是不删除。如果集合中没有元素,会返回null。
peekFirst();
peekLast();
3)删
获取元素,并删除元素。如果集合中没有元素,会返回null。
pollFirst();
pollLast();
示例代码:
LinkedList ll = new LinkedList();
//在集合尾部增加元素
ll.offerLast("java01");
ll.offerLast("java02");
ll.offerLast("java03");
System.out.println(ll);
//获取集合中第一个元素
System.out.println("the first element in LinkedList is :"+ll.peekFirst());
//删除集合中最后一个元素
ll.pollLast();
System.out.println("after pollLast: ");
//链表输出方式
while(!ll.isEmpty()){
System.out.print(ll.poll()+"\t");
运行截图:
模拟堆栈和队列:
/*
使用LinkedList模拟一个堆栈或者队列数据结构
堆栈:后进先出, 如同一个杯子
队列:先进先出, 如同一个水管
*/
//队列
class Duilie{
private LinkedList link;
public Duilie(){
link = new LinkedList();
}
public void myAdd(Object obj){
link.addLast(obj);
}
public Object myGet(){
Object obj = link.removeFirst();
return obj;
}
public boolean isNull(){
return link.isEmpty();
}
}
//堆栈
class Stack{
private LinkedList link;
public Stack(){
link = new LinkedList();
}
public void myAdd(Object obj){
link.addLast(obj);
}
public Object myGet(){
Object obj = link.removeLast();
return obj;
}
public boolean isNull(){
return link.isEmpty();
}
}
四、Set
Set集合的功能和Collection是一致的
Set:元素是无序的(存入和取出第顺序不一定一致),元素不可以重复
|--HashSet:底层数据结构是哈希表。
|--TreeSet:
1.HashSet
HashSet:底层数据结构是哈希表,线程不同步。
如果元素的hashCode值相同,才会判断equals是否为true。
如果元素的哈希值不同,不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的是元素的哈希值和equals方法
示例代码:
/*
在HashSet中存储自定义对象
*/
public class SetDemo {
public static void main(String[] args) {
Set hashSet = new HashSet(); //多态
//添加数据
hashSet.add(new Person("person01", 18));
hashSet.add(new Person("person02", 28));
hashSet.add(new Person("person03", 19));
hashSet.add(new Person("person02", 28)); //重复元素,添加不进去
//输出
System.out.println("\n集合中的元素为:");
for(Iterator iter = hashSet.iterator(); iter.hasNext();){
Person p = (Person)iter.next();
System.out.println(p.getName()+"...."+p.getAge());
}
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写hashCode方法
public int hashCode(){
System.out.println(this.name+"-----hashCode");
return this.name.hashCode() + this.age * 39;
}
//重写equals方法
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
System.out.println(this.name+"----equals----"+p.getName());
if(this.name.equals(p.getName()) && this.age == p.age)
return true;
return false;
}
}
运行截图
从运行结果可以看出,每次添加元素都会调用hashCode方法获取哈希值进行判断,如果哈希值不同就将元素添加进去,如果哈希值相同则继续调用equals方法判断是否是同一个对象,如果是同一个对象则不添加
2.TreeSet
TreeSet:底层的数据结构为二叉树结构(红黑树结构),线程不同步。
可以对Set集合中的元素进行排序。因为TreeSet类实现了NavigableSet接口,该接口强制让增加到集合中的对象进行了比较,使用元素的自
然顺序对元素进行排序,元素所在类需要实现Comparable接口并复写compareTo方法,或者根据创建 set 时提供的 Comparator进行排序,
具体取决于使用的构造方法。
java中的很多类都具备比较性,其实就是实现了Comparable接口。注意:排序时,当主要条件相同时,可以增加对次要条件的比较。
对于增加元素、判断元素是否存在,以及删除等操作,依赖的是元素的compareTo方法或者传入的比较器中compare方法的
返回值,是正整数、负整数或零,则两个对象较大、较小或相同。相等时则不会存入。
二叉树示意图
值得注意的是每增加完一个元素,二叉树都会根据平衡二叉树的原理调整原来得二叉树结构
1.Tree排序的两种方式
1)第一种排序方式:自然排序
让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。
示例代码:
public class TreeSetDemo {
public static void main(String[] args) {
Set ts = new TreeSet();
//添加元素
ts.add(new Person("lili1", 20));
ts.add(new Person("lili2", 21));
ts.add(new Person("lili3", 22));
ts.add(new Person("lili4", 24));
ts.add(new Person("lili3", 23));
//迭代输出
System.out.println("集合内容是:");
for(Iterator iter=ts.iterator(); iter.hasNext();)
System.out.println(iter.next());
}
}
class Person implements Comparable{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写hashCode方法
public int hashCode(){
System.out.println(this.name+"-----hashCode");
return this.name.hashCode() + this.age * 39;
}
//重写equals方法
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
System.out.println(this.name+"----equals----"+p.getName());
if(this.name.equals(p.getName()) && this.age == p.age)
return true;
return false;
}
//覆写Object类的toString方法
public String toString(){
return this.name+"----"+this.age;
}
//覆写Comparable接口中的compareTo方法
public int compareTo(Object o) {
Person p = (Person)o;
System.out.println(this.getName()+"--compare--"+p.getName());
int num = this.getName().compareTo(p.getName());//String实现了Comparable接口,并覆写了compareTo方法,这里直接调用
//如果名字相同则比较年龄
if(num==0){
if(this.age > p.getAge())
return 1;
else if(this.age < p.getAge())
return -1;
else return 0;
}
return num;
}
}
运行截图:
由运行结果可知,每次插入元素都会调用compareTo方法进行比较,且会不断的调整二叉树的结构。
2)第二种排序方式:传入比较器
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
比较器构造方式:定义一个类,实现Comparator接口,覆盖compare方法。
注意:当两种排序都存在时,以比较器为主。
示例代码:
public class TreeSetDemo {
public static void main(String[] args) {
Set ts = new TreeSet(new MyComparator()); //带比较器的集合
//添加元素
ts.add(new Person("lili1", 20));
ts.add(new Person("lili2", 21));
ts.add(new Person("lili3", 22));
ts.add(new Person("lili4", 24));
ts.add(new Person("lili3", 23));
//迭代输出
System.out.println("集合内容是:");
for(Iterator iter=ts.iterator(); iter.hasNext();)
System.out.println(iter.next());
}
}
//自定义比较器
class MyComparator implements Comparator{
//覆写Comparator接口的compare方法
public int compare(Object o1, Object o2) {
Person p1 = (Person)o1;
Person p2 = (Person)o2;
System.out.println(p1.getName()+"--compare--"+p2.getName());
int num = p1.getName().compareTo(p2.getName());
//姓名相同时调用Integer类实现的compareTo方法
if(num==0)
return new Integer(p1.getAge()).compareTo(new Integer(p2.getAge()));
return num;
}
}
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写hashCode方法
public int hashCode(){
System.out.println(this.name+"-----hashCode");
return this.name.hashCode() + this.age * 39;
}
//重写equals方法
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
System.out.println(this.name+"----equals----"+p.getName());
if(this.name.equals(p.getName()) && this.age == p.age)
return true;
return false;
}
//覆写Object类的toString方法
public String toString(){
return this.name+"----"+this.age;
}
}
运行截图:
运行结果和之前的一模一样
五、Map---键值对
Map集合:该集合存储键值对。一对一往里存,而且要保证键的唯一性
注意:Hashtable、HasgMap中要保证键的唯一性,则作为键存入到对象必须重写hashCode方法和equals方法
TreeMap中则实现Comparable接口重写CompareTo方法,或者向TreeMap对象中传入比较器
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键和null值。该集合是线程同步的。JDK1.0 效率低。
|--HashMap:底层是哈希表数据结构,允许使用null值和null键。该集合是不同步的。JDK1.0 效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
和Set很像。
其实Set底层就是使用了Map集合。
1.常用方法
1)添加
V put(K key, V value);
注意:如果要放入的key不存在,则返回;如果已经存在,则返回key对应的value,并且将集合中原来得value替换为新的value
void putAll(Map<? extends k,? extends V> m);
2)删除
clear();
remove(Object key);
3)判断
containsKey(Object Key);
containsValue(Object value);
isEmpty();
4)获取
V get(Object key); 通过键获取值
int size(); 获取长度
Collection<V> values(); 得到值的集合
Map集合输出的两种方式
Set<K> keySet(); 得到键的Set集合,因为键是不允许重复的,所以这里用的Set集合
Set<Map.Entry<K,V>> entrySet(); 返回此映射中包含的映射关系的 Set 视图
示例代码:
public class MapDemo {
public static void main(String[] args) {
Map hashMap = new HashMap();
//添加元素
hashMap.put("01", "lily01");
hashMap.put("02", "lily02");
hashMap.put("03", "lily03");
hashMap.put("04", "lily04");
//键可以取null值
hashMap.put(null, "lily");
//添加元素,如果出现要添加的键已经存在,那么后添加到值会覆盖原有键对应的值,并且put方法会返回被覆盖的值。
System.out.println(hashMap.put("05", "lily05"));
System.out.println(hashMap.put("05", "new lily05"));
//一些操作
// System.out.println("containsKey:"+hashMap.containsKey("02"));
// System.out.println("remove:"+hashMap.remove("02"));
//可以通过get方法都返回值来判断一个键是否存在,通过返回null来判断
// System.out.println("get:"+hashMap.get("01"));
//获取Map集合中所有的值
Collection coll = hashMap.values();
System.out.println("所有的value:"+coll);
System.out.println("hashMap:"+hashMap); //HashMap内重写了toString方法
}
}
2.Map集合输出的两种方式
Map集合的取出原理:将map集合转成set集合,再通过迭代器取出。
1)Set<K> keySet:将map中所有的键存入到Set集合。因为Set具备迭代器。
所以可以用迭代方式取出的所有的键,再根据get方法获取每一个键对应的值
示例代码:
public class MapDemo {
public static void main(String[] args) {
Map hashMap = new HashMap();
//添加元素
hashMap.put("01", "lily01");
hashMap.put("04", "lily02");
hashMap.put("03", "lily03");
hashMap.put("02", "lily04");
//先获取map集合的所有键的set集合,keySet();
Set keySet = hashMap.keySet();
//有了Set集合,就可以获取其迭代器
Iterator iter = keySet.iterator();
while(iter.hasNext()){
String key = (String)iter.next();
//有了键可以通过map集合的get方法获取其对应的值
String value = (String)hashMap.get(key);
System.out.println("key:"+key+", value:"+value);
}
}
}
2)Set<Map.Entry<K,V>> entrySet:将map集合中映射放系存入到了set集合中,而这个关系的数据类型就是:Map.Entry
其实Entry是Map接口中的一个内部接口
interface Map{
public static interface Entry{
public abstract Object getKey();
public abstract Object getValue();
}
}
注:之所以定义在Map接口的内部:①先有Map这个集合,才有映射关系的存在,而且此类关系是集合的内部事务
②可以直接访问Map集合中的内部成员
示例代码:
public class MapDemo {
public static void main(String[] args) {
Map hashMap = new HashMap();
//添加元素
hashMap.put("01", "lily01");
hashMap.put("04", "lily02");
hashMap.put("03", "lily03");
hashMap.put("02", "lily04");
//将Map集合中的映射关系取出,存入到set集合中
Set<Map.Entry> entry = hashMap.entrySet();
Iterator iter = entry.iterator();
while(iter.hasNext()){
Map.Entry oo= (Map.Entry)iter.next();
String key = (String)oo.getKey();
String value = (String)oo.getValue();
System.out.println("key"+key+", value:"+value);
}
}
}<span style="font-size:14px;">
</span>
3.TreeMap---key排序的Map
实现方式和TreeMap相同,1)key所在类实现Comparable接口重写compareTo方法。2)向TreeMap对象传入构造器
示例代码:
/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名年龄相同的视为同一个学生。
保证学生的唯一性。
两种排序方式,1)按姓名排 2)按年龄排
*/
public class MapTest {
public static void main(String[] args) {
Map tm = new TreeMap();
// Map tm = new TreeMap(new MyComparator2()); //帶比較器
//添加元素
tm.put(new Student("lily03", 21), "beijing");
tm.put(new Student("lily02", 25), "shanghai");
tm.put(new Student("lily04", 29), "wuhan");
tm.put(new Student("lily01", 23), "shenzhen");
// tm.put(new Student("lily04", 29), "wuhan1");
//输出
Set keySet = tm.keySet();
for(Iterator iter=keySet.iterator(); iter.hasNext();){
Student key = (Student)iter.next();
String value = (String)tm.get(key);
System.out.println(key+"---"+value);
}
}
}
//自定义比较器,以年龄为主要比较条件,姓名为次要比较条件
class MyComparator2 implements Comparator{
//重写compare方法
public int compare(Object o1, Object o2) {
Student s1 = (Student)o1;
Student s2 = (Student)o2;
int num = new Integer(s1.getAge()).compareTo(s2.getAge());
if(num==0)
return s1.getName().compareTo(s2.getName());
return num;
}
}
class Student implements Comparable{
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//覆写toString方法
public String toString() {
return this.name+"::"+this.age;
}
//覆写hashCode方法
public int hashCode() {
return this.name.hashCode()+this.age*39;
}
//覆写equals方法
public boolean equals(Object obj) {
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s = (Student)obj;
return this.name.equals(s.getName()) && this.age == s.getAge();
}
//重写compareTo方法,已姓名作为主要条件排序,年龄作为次要条件
public int compareTo(Object o) {
Student s = (Student)o;
int num = this.getName().compareTo(s.getName());
if(num==0)
return new Integer(this.getAge()).compareTo(s.getAge());
return num;
}
}
运行截图:
4.Map练习
1)“dkjdkjdishkalbkjdbifd"获取该字符串中字符出现的次数,
希望打印结果:a(1)d(2)...
通过结果发现,每一个字母都有对应的次数
说明字母和次数之间都有映射关系,可以用Map集合来描述
示例代码:
/*
1.将字符串变成字符数组
2.定义一个map集合,将字母和对应的次数都存进去
3.遍历字符数组,如果字母已经存在则次数加1,否则就存入
4.将map集合转换成字符串
*/
public class MapTest2 {
public static void main(String[] args) {
String str = "alkjkldoskjaljaldjf";
System.out.println(getCount(str));
}
//获取字符串中字母出现次数
static String getCount(String str){
char[] buf = str.toCharArray();
//定义map集合
Map<Character, Integer> tm = new TreeMap<Character, Integer>();
for(int i=0, count=0; i<buf.length; i++, count=0){
//非法字符则不会存入集合
if(buf[i]<'a' || buf[i]>'z' || buf[i]<'A' || buf[i]>'Z')
continue;
Integer value = tm.get(buf[i]);
if(value != null) //字母在集合中存在则次数加1,不然就存入该字母
count = value;
count++;
tm.put(buf[i], count);
}
//定义一个字符串容器
StringBuilder sb = new StringBuilder();
//取出集合中的数据,并转换成指定字符串
Set<Map.Entry<Character, Integer>> entrySet = tm.entrySet();
for(Iterator<Map.Entry<Character, Integer>> iter=entrySet.iterator(); iter.hasNext();){
Map.Entry<Character, Integer> entry = iter.next();
sb.append(entry.getKey()+"("+entry.getValue()+")");
}
return sb.toString();
}
}
5.Map应用扩展
用Map实现多重映射
/*
Map--多重映射
学校有预热班和就业班
预热班和就业班分别有自己的学生信息
*/
public class MapTest3 {
public static void main(String[] args) {
//预热班集合
Map<String, String> yure = new HashMap<String, String>();
yure.put("01", "lily");
yure.put("02", "lily02");
//就业班集合
Map<String, String> jiuye = new HashMap<String, String>();
jiuye.put("01", "coco");
jiuye.put("02", "coco02");
//学校集合
Map<String, Map<String, String>> school = new HashMap<String, Map<String, String>>();
//将预热班集合和就业班集合添加到学校集合中
school.put("yure", yure);
school.put("jiuye", jiuye);
//输出所有学生信息
Iterator<String> iter = school.keySet().iterator();
while(iter.hasNext()){
String key = iter.next();
//获得班级学生信息集合
Map<String, String> ban = school.get(key);
//根据传入的班级输出学生信息
out(ban);
}
}
//按班级输出学生信息
public static void out(Map<String, String> ban){
Iterator<String> iter = ban.keySet().iterator();
while(iter.hasNext()){
String key = iter.next();
String value = ban.get(key);
System.out.println(key+"::"+value);
}
}
}