------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! ------
集合框架
java中有许多的集合,也称为容器,下图便是集合框架的构成及分类。
一、为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
二、数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
三、集合类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
Collection
Collection是集合框架中的常用接口。其下有两个子接口:List(列表),Set(集)。
所属关系:
Collection
|--List//元素是有序的,元素可以重复。因为该集合体系有索引。
|--Set//元素是无序的,元素不可以重复。
以下是Collection的总述:
1 import java.util.*; 2 /* 3 Collection定义了集合框架的共性功能。 4 5 1 添加 6 add(e); 7 addAll(collention); 8 2 删除 9 remove(e) 10 removeAll(collection); 11 clear(); 12 3 判断 13 contains(e) 14 isEmpty(); 15 4 获取 16 iterator() 迭代器iterator() 17 size(); 18 5 获取交集 19 retainAll() 20 6 集合变数组 21 toArray() 22 23 1 add方法的参数类型是Object。以便于接收任意类型对象 24 2 集合中存储的都是对象的引用(地址) 25 26 迭代器 27 28 什么是迭代器呢? 29 其实就是集合的取出元素的方式 30 如同抓娃娃游戏机中的夹子 31 32 迭代器是去除方式,会直接访问集合中的元素 33 所以将迭代器通过内部类的形式来进行描述 34 通过容器的Iterator()方法获取该内部类的对象 35 2、迭代注意事项 36 37 迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)。 38 迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。 39 迭代器的next方法返回值类型是Object,所以要记得类型转换。 40 41 */ 42 class CollectionDemo 43 { 44 public static void main(String[] args) 45 { 46 method_get(); 47 } 48 public static void sop(Object obj)//打印一切对象 49 { 50 System.out.println(obj); 51 } 52 53 public static void base_method() 54 { 55 //创建一个集合容器。使用Collection接口的子类。ArrayList 56 ArrayList al = new ArrayList(); 57 58 //1,添加元素。 59 al.add("java01");//add(Object obj); 60 al.add("java02"); 61 al.add("java03"); 62 al.add("java04"); 63 64 //打印原集合。 65 sop("原集合:"+al); 66 67 68 //3,删除元素。 69 //al.remove("java02"); 70 //al.clear();//清空集合。 71 72 73 //4,判断元素。 74 sop("java03是否存在:"+al.contains("java03")); 75 sop("集合是否为空?"+al.isEmpty()); 76 77 78 //2,获取个数。集合长度。 79 sop("size:"+al.size()); 80 81 //打印改变后的集合。 82 sop(al); 83 84 } 85 86 public static void method_get() 87 { 88 ArrayList a1=new ArrayList();//创建一个列表集合 89 a1.add("java01");//添加元素 90 al.add("java02"); 91 al.add("java03"); 92 al.add("java04"); 93 /* 94 Iterator it=a1.iterator();//获取迭代器,用于取出集合中的元素 95 while(it.hasNext()) 第一种打印方式: 96 { 97 sop(it.next()); 98 } 99 */ 100 //第二种打印方式:,相对于第一种节省了开辟it的资源。 101 for(Iterator it=a1.iterator();it.hasNext();) 102 { 103 sop(it.next());//在迭代时循环中next调用一次,就要hasNext判断一次。 104 } 105 } 106 public static void method_2() 107 { 108 ArrayList a11=new ArrayList();//创建集合对象 109 a11.add("java01"); 110 al1.add("java02"); 111 al1.add("java03"); 112 al1.add("java04"); 113 ArrayList al2 = new ArrayList();//创建集合对象 114 115 al2.add("java03"); 116 al2.add("java04"); 117 al2.add("java05"); 118 al2.add("java06"); 119 120 a11.retainAll(a12);//取交集,保留在a11中 121 sop("a11:"+a11); 122 123 124 a11.IndexOf(2,"java110");//在 a11集合中 用java110替代 位置2 上的元素 125 sop("a11:"+a11); 126 } 127 }
List
一、List
组成
List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
二、List的特有方法
凡是可以操作角标的方法都是该体系特有的方法。
1、增
booleanadd(index,element);//指定位置添加元素
BooleanaddAll(index,Collection);//在指定位置增加给定集合中的所有元素,若省略位置参数,则在当前集合的后面依次添加元素
2、删
Booleanremove(index);//删除指定位置的元素
3、改
set(index,element);//修改指定位置的元素。
4、查
get(index);//通过角标获取元素
subList(from,to);//获取部分对象元素
5、其他
listIterator();//List特有的迭代器
indexOf(obj);//获取元素第一次出现的位置,如果没有则返回-1
注:List集合判断元素是否相同,移除等操作,依据的是元素的equals方法。
三、ListIterator
1、概述
ListIterator是List集合特有的迭代器,是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以在迭代器时,只能用迭代器的方法操作元素。可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。该接口只能通过List集合的ListIterator方法获取。
2、ListIterator特有的方法
add(obj);//增加
set(obj);//修改为obj
hasPrevious();//判断前面有没有元素
previous();//取前一个元素
四、枚举Enumeration
枚举:
就是Vector特有的取出方式。Vector有三种取出方式。
其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。
特有方法:
addElement(obj);//添加元素,相当于add(obj);
Enumerationelements();//Vector特有取出方式(枚举)
hasMoreElements();//相当于Iterator的hasNext()方法
nextElements();//相当于Iterator的next()方法
例:
1 import java.util.*; 2 /* 3 枚举就是Vector特有的取出方式。 4 发现枚举和迭代器很像。 5 其实枚举和迭代是一样的。 6 因为枚举的名称以及方法的名称都过长。 7 所以被迭代器取代了。 8 枚举郁郁而终了。 9 */ 10 class VectorDemo 11 { 12 public static void main(String[] args) 13 { 14 Vector v = new Vector();//创建容器 15 16 v.add("java01");//添加元素 17 v.add("java02"); 18 v.add("java03"); 19 v.add("java04"); 20 21 Enumeration en = v.elements();//枚举 22 23 while(en.hasMoreElements())//遍历,只要存在元素 24 { 25 System.out.println(en.nextElement()); 26 } 27 } 28 }
五、LinkedList
1 import java.util.*; 2 /* 3 LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。 4 LinkedList:特有方法 5 addFirst(); 6 addLast(); 7 8 removeFirst();获取删除,当空时,出现异常 9 removeLast(); 10 11 getFirst();获取不删除 12 getLast(); 13 14 offerFirst(); 15 offerLast(); 16 17 peekFirst(); 18 peekLast(); 19 20 pollFirst(); 21 pollLast(); 22 23 24 */ 25 /* 26 使用LinkedList模拟一个堆栈或者队列数据结构 27 28 堆栈:先进后出 如同一个杯子 29 队列:先进先出First in First out FIFO 如同一个水管 30 */ 31 import java.util.*; 32 class DuiLie 33 { 34 private LinkedList link;//将队列私有化 35 DuiLie() //创建新的队列 36 { 37 link=new LinkedList(); 38 } 39 public void myAdd(Object obj)//增加新元素 40 { 41 link.addFirst(obj); 42 } 43 public Object myGet() //获得元素,先进后出 堆栈 44 { 45 return link.removeFirst(); 46 } 47 public Object myGet2()//获得元素 先进先出 队列 48 { 49 return link.removeLast(); 50 } 51 public boolean isNull() //判断是否为空 52 { 53 return link.isEmpty(); 54 } 55 } 56 class LinkedListTest 57 { 58 public static void sop(Object obj) 59 { 60 System.out.println(obj); 61 } 62 public static void main(String[] args) 63 { 64 DuiLie d1=new DuiLie(); 65 d1.myAdd("java01"); 66 d1.myAdd("java02"); 67 d1.myAdd("java03"); 68 d1.myAdd("java04"); 69 while(!d1.isNull()) 70 { 71 System.out.println(d1.myGet());//先进后出 堆栈 72 System.out.println(d1.myGet2());//先进先出 队列 73 } 74 sop(d1); 75 } 76 }
Set
一、概述
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
|--HashSet:底层数据结构是哈希表。线程不同步。 保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。
|--TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0。
Set集合的功能和Collection是一致的。
二、HasSet
HashSet:线程不安全,存取速度快。
可以通过元素的两个方法,hashCode和equals来完成保证元素唯一性。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。
注意:HashSet对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。
示例:
1 /* 2 往hashSet集合中存入自定对象 3 姓名和年龄相同为同一个人,重复元素。 4 思路:1、对人描述,将人的一些属性等封装进对象 5 2、定义一个HashSet容器,存储人对象 6 3、取出 7 */ 8 import java.util.*; 9 class HashSetTest 10 { 11 public static void sop(Object obj)//打印任何对象 12 { 13 System.out.println(obj); 14 } 15 public static void main(String[] args) 16 { 17 HashSet hs = new HashSet();//建立集合 18 hs.add(new Person("a1",11));//存储元素 19 hs.add(new Person("a2",12)); 20 hs.add(new Person("a3",13)); 21 //hs.add(new Person("a2",12)); 22 //hs.add(new Person("a4",14)); 23 //sop("a1:"+hs.contains(new Person("a2",12))); 24 //hs.remove(new Person("a4",13)); 25 Iterator it = hs.iterator();//调用集合 共有的 迭代器 26 27 while(it.hasNext())//遍历集合, 28 { 29 Person p = (Person)it.next(); 30 sop(p.getName()+"::"+p.getAge()); 31 } 32 } 33 } 34 class Person//创建人对象,并对其进行描述 35 { 36 private String name; 37 private int age; 38 Person(String name,int age) 39 { 40 this.name = name; 41 this.age = age; 42 } 43 public int hashCode()//自定义 哈希值 44 { 45 System.out.println(this.name+"....hashCode"); 46 return name.hashCode()+age*37; 47 } 48 49 public boolean equals(Object obj)//复写equals方法,定义自己的比较方式 50 { 51 if(!(obj instanceof Person))//先确定调用的obj是不是 人类 52 return false; 53 54 Person p = (Person)obj;//向下转型,使obj的身份变为person 55 System.out.println(this.name+"...equals.."+p.name); 56 return this.name.equals(p.name) && this.age == p.age;//先比较姓名再比较年龄 57 } 58 59 60 public String getName()//返回姓名 61 { 62 return name; 63 } 64 public int getAge()//返回年龄 65 { 66 return age; 67 } 68 }
三、TreeSet
1、特点
a、底层的数据结构为二叉树结构(红黑树结构)
b)可对Set集合中的元素进行排序,是因为:TreeSet类实现了Comparable接口,该接口强制让增加到集合中的对象进行了比较,需要复写compareTo方法,才能让对象按指定需求(如人的年龄大小比较等)进行排序,并加入集合。
java中的很多类都具备比较性,其实就是实现了Comparable接口。
注意:排序时,当主要条件相同时,按次要条件排序。
1)第一种排序方式:自然排序
让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。
示例:
1 /* 2 TreeSet 排序的第一种方式,让元素自身具备比较性 3 元素需要实现Comparable接口,覆盖compareTo方法 4 这种方式也称为元素的自然顺序,或者叫做默认顺序 5 */ 6 import java.util.*; 7 class TreeSetDemo 8 { 9 public static void main(String[] args) 10 { 11 TreeSet ts=new TreeSet();//建立二叉树集合对象 12 ts.add(new Student("lisi02",22));//添加元素进集合 13 ts.add(new Student("lisi007",20)); 14 ts.add(new Student("lisi09",19)); 15 ts.add(new Student("lisi08",19)); 16 ts.add(new Student("lisi007",20)); 17 ts.add(new Student("lisi01",40)); 18 19 Iterator it = ts.iterator();//调用集合中的迭代器 20 while(it.hasNext())//遍历 容器成员 21 { 22 Student stu = (Student)it.next(); 23 System.out.println(stu.getName()+"..."+stu.getAge()); 24 } 25 } 26 } 27 class Student implements Comparable//该接口赋予了学生具备比较性 28 { 29 private String name; 30 private int age; 31 Student(String name,int age) 32 { 33 this.name=name; 34 this.age=age; 35 } 36 public int compareTo(Object obj)//复写compareTo方法 37 { 38 if(!(obj instanceof Student))//判断obj是否为学生对象 39 throw new RuntimeException("不是学生对象"); 40 Student s=(Student)obj;//向下转型 41 System.out.println(this.name+".....compareto..."+s.name); 42 if(this.age>s.age) 43 return 1; 44 if(this.age==s.age)//如果年龄相等,便运用字符串的比较方式 45 { 46 return this.name.compareTo(s.name); 47 } 48 return -1; 49 } 50 public String getName()//获取姓名方法 51 { 52 return name; 53 } 54 public int getAge()//返回年龄 55 { 56 return age; 57 } 58 }
2)第二种方式:比较器
1 import java.util.*; 2 /* 3 当元素自身不具备比较性,或者具备的比较性不是所需要的 4 这时需要让容器自身具备比较性 5 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数 6 7 当两种排序都存在时,以比较器为主 8 9 定义一个类,实现Comparator接口,覆盖compare方法 10 11 */ 12 class TreeSetDemo2 13 { 14 public static void main(String[] args) 15 { 16 TreeSet ts = new TreeSet(); 17 18 ts.add(new Student("lisi02",22)); 19 ts.add(new Student("lisi02",21)); 20 ts.add(new Student("lisi007",20)); 21 ts.add(new Student("lisi09",19)); 22 ts.add(new Student("lisi06",18)); 23 ts.add(new Student("lisi06",18)); 24 ts.add(new Student("lisi007",29)); 25 //ts.add(new Student("lisi007",20)); 26 //ts.add(new Student("lisi01",40)); 27 28 Iterator it = ts.iterator();//调用集合中的迭代器,用于遍历 29 while(it.hasNext())//遍历集合,每次调用it.next,都要判断该语句 30 { 31 Student stu = (Student)it.next(); 32 System.out.println(stu.getName()+"..."+stu.getAge()); 33 } 34 } 35 } 36 class Student implements Comparable//该接口让学生具备比较性 37 { 38 private String name; 39 private int age; 40 Student(String name,int age) 41 { 42 this.name=name; 43 this.age=age; 44 } 45 public String getName() 46 { 47 return name; 48 } 49 public int getAge() 50 { 51 return age; 52 } 53 public int compareTo(Object obj)//复写compareTo方法,定义自己的比较方式 54 { 55 if(!(obj instanceof Student)) 56 throw new RuntimeException("不是学生对象"); 57 Student s=(Student)obj; 58 if(this.age>s.age) 59 return 1; 60 if(this.age==s.age) 61 { 62 return this.name.compareTo(s.name); 63 } 64 return -1; 65 } 66 } 67 68 class MyCompare implements Comparator//创建比较器,实现Comparator接口 69 { 70 public int compare(Object o1,Object o2) 71 { 72 Student s1=(Student)o1; 73 Student s2=(Student)o2; 74 int num = s1.getName().compareTo(s2.getName());//比较姓名 75 if(num==0) 76 { 77 return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));//后比较年龄 78 } 79 return num; 80 } 81 82 } 83 class StrLenComparator implements Comparator//创建长度比较器,实现Comparator接口 84 { 85 public int compare(Object obj1,Object obj2) 86 { 87 String s1=(String)obj1; 88 String s2=(String)obj2; 89 if(s1.length()>s2.length())//比较长度 90 return 1; 91 if(s1.length()>s2.length()) 92 { 93 return s1.compareTo(s2); 94 } 95 return -1; 96 } 97 }
自我总结:
List接口有三个实现类:LinkedList,ArrayList,Vector
LinkedList:底层基于链表实现,链表内存是散乱的,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢
ArrayList和Vector的区别:ArrayList是非线程安全的,效率高;Vector是基于线程安全的,效率低
List是用来处理序列的,而set是用来处理集的。