引入集合类的原因:java数组是固定长度的,数组在创建的时候就指定了长度,在一些情况下长度并不是一定的,这时就需要用集合来进行数据存储。使用集合还可以在其中放对象的引用,但不能存放基本数据类型。
集合分类:Set(集合):集合中对象不按特定的方式排序,并且没有重复对象,但它有些实现类中的对象按特定方式排序。
List(列表):集合中的对象按检索位置排序,可以有重复对象,允许按照对象在集中的索引位置检索对象,和数组类似。
Map(映射):集合的每一个元素包含一对键对象和值对象,集合中没有重复的键对现象,值对象可以重复,它的有些实现类能对集合中的键对象进行排序。
1. List和Set继承自Collection接口
2. 排序的操作接口:SortedMap、SortedSet
3. 输出的操作接口:Iterator、ListIterator、Enumeration
Collection定义了如下方法:
1 |
Public boolean add(E e) |
普通 |
向集合中增加元素 |
2 |
boolean addAll(Collection<? extends E> c) |
普通 |
向集合中加入一组数据 |
3 |
void clear() |
普通 |
清空所有内容 |
4 |
boolean contains(Object o) |
普通 |
判断是否有制定内容,查找 |
5 |
boolean equals(Object o) |
普通 |
对象比较 |
6 |
int hashCode() |
普通 |
返回hash码 |
7 |
boolean isEmpty() |
普通 |
判断集合内容是否为空 |
8 |
Iterator<E> iterator() |
重要 |
为Iterator接口实例化,迭代输出 |
9 |
boolean remove(Object o) |
普通 |
从数组中删除指定对象 |
10 |
boolean retainAll(Collection<?> c) |
普通 |
|
11 |
int size() |
普通 |
取得数组大小 |
12 |
Object[] toArray() |
|
取得全部内容,以数组形式返回 |
13 |
<T> T[] toArray(T[] a) |
|
取得全部内容 |
Collection接口的iterator()和toArray()方法都可以获得集合中的所有元素,前者返回Iterator对象,后者返回一个包含集合中所有元素的数组。
Iterator隐藏底层集合的数据结构,向客户程序提供了遍历各种类型的集合的统一接口。
Iterator接口中声明了如下方法: hasNext():判断集合中的元素是否遍历完毕,如果没有,就返回true。 next():返回下一个元素 remove():从集合中删除上一个由next()方法返回的元素。
如果集合中的元素没有排序,Iterator遍历集合中元素的顺序是任意的,并不一定与像集合中加入的元素的顺序一致。
Set:
Set是最简单的一种集合,集合中的对象不按特定方式排序,并没有重复对象。Set接口主要有两个实现类:HashSet类还有一个子类LinkedHashSet类,它不仅实现了哈希算法,而且实现了链表数据结构,链表数据结构能提高插入核算出元素的性能。TreeSet类实现了SortedSet接口中,具有排序功能。
List:
List的主要特征是先创建就先存储,集合中允许存放重复对象。List接口主要的实现类包括:ArrayList—ArrayList代表长度可变的数组。允许对元素进行快速的随机访问,但是向ArrayList中插入与删除元素的速度较慢。LinkedList—在实现中采用链表数据结构。对顺序访问进行了优化,向List中插入和删除元素的速度较快,随机访问速度则相对较慢,随机访问是指检索位于特定索引位置元素。
Map:
Map(映射)是一种把键对和值对象进行映射的集合。它的每一个元素都包含一对键对象和值对象,而之对象仍可以是Map类型。 以此类推,这样就形成了多级映射。向Map集合中加入元素时,必须提供一对键对象和值对象,从Map集合上检索元素只要给出键对象,就会返回值对象。
Set接口:
1. HashSet类:
HashSet按照哈希算法—存取集合中的对象,具有很好的存取和查找功能。当向集合中加入对象,调用hashCode()方法来多出hash码,根据hash码计算对象在集合中的存放位置。
public class HashSetDemo {
/**
* @param args
* 无序的 不能添加重复元素
* Object类中的hashCode()和equals()方法完成重复元素的验证
* 一个完整的类必须覆写Object类中的hashCode和equals方法
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Set allSet=new HashSet();
allSet.add("hehe");
allSet.add("haha");
allSet.add("Hello!!");//增加相同的元素
allSet.add("Hello!!");//增加相同的元素
allSet.add("Hello!!");//增加相同的元素
allSet.add("World!!");
System.out.println(allSet);
Set<Person1> allSet1=new HashSet<Person1>();
allSet1.add(new Person1("张三",78));
allSet1.add(new Person1("赵六",23));
allSet1.add(new Person1("王五",14));
allSet1.add(new Person1("李四",56));
allSet1.add(new Person1("陈八",9));//增加相同的元素
allSet1.add(new Person1("陈八",9)); //年龄相同 默认会认为是同一个对象,要改正这一现象需要在compareTo中 return 0更改
//实现同步
//Set s = Collections.synchronizedSet(new HashSet(...));
System.out.println(allSet1);
}
}
class Person1 implements Comparable<Person1>{ //实现comparable接口进行比较
private String name;
private int age;
public Person1(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+this.name+";年龄:"+this.age;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(this==obj){
return true;
}
if(!(obj instanceof Person1)){
return false;
}
Person1 p=(Person1)obj;
if(this.name.equals(p.name)&&this.age==p.age){
return true;
}else {
return false;
}
}
public int hashCode(){ //这个方法的返回值都是通过一个公式计算的
//此时的公式:名字的hashcode * age
return this.name.hashCode() * this.age;
}
@Override
public int compareTo(Person1 o) {
// TODO Auto-generated method stub
if(this.age>o.age){
return 1;
}else if(this.age<o.age){
return -1;
}else{
//return 0;
return this.name.compareTo(o.name);
}
}
}
2. TreeSet类:
能够对集合中的对象进行排序
3. public class TreeSetDemo {
4.
5. /**
6. * @param args
7. * 可以排序的 不允许重复
8. * 一个自定义的类本身不知道该如何排序 对象所在的类必须实现Comparable接口,并覆写compareTo()方法
9. */
10. public static void main(String[] args) {
11. // TODO Auto-generated method stub
12. Set<Person> allSet=new TreeSet<Person>();
13. allSet.add(new Person("张三",78));
14. allSet.add(new Person("赵六",23));
15. allSet.add(new Person("王五",14));
16. allSet.add(new Person("李四",56));
17. allSet.add(new Person("孙七",9));//增加相同的元素
18. allSet.add(new Person("陈八",9)); //年龄相同 默认会认为是同一个对象,要改正这一现象需要在compareTo中return 0更改
19. System.out.println(allSet);
20. }
21.
22. }
23. class Person implements Comparable<Person>{
24. private String name;
25. private int age;
26. public Person(String name, int age) {
27. super();
28. this.name = name;
29. this.age = age;
30. }
31. public String toString(){
32. return "姓名:"+this.name+";年龄:"+this.age;
33. }
34. @Override
35. public int compareTo(Person o) {
36. // TODO Auto-generated method stub
37. if(this.age>o.age){
38. return 1;
39. }else if(this.age<o.age){
40. return -1;
41. }else{
42. //return 0;
43. return this.name.compareTo(o.name);
44. }
45. }
46.
47. }
List接口:最大的特点是里面的内容都可以重复。
1 |
Public void add(int index,E element) |
普通 |
在指定位置处加入元素 |
2 |
Public Boolean addAll(int index ,Collection<?extends E>c) |
普通 |
在指定位置增加一组元素 |
3 |
Public E get(int index) |
普通 |
通过索引位置可以取出每一个元素 |
4 |
Public E remove(int index) |
普通 |
删除指定位置内容 |
5 |
Public E set(int index,E element) |
普通 |
修改指定位置内容 |
6 |
Public List<E> subList(int fromIndex,int toIndex) |
普通 |
截取子集合 |
7 |
Public int lastIndexOf(Object o) |
普通 |
返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1 |
8 |
Public int indexOf(Object o) |
普通 |
回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1 |
9 |
ListIterator<E> listIterator() |
普通 |
返回此列表元素的列表迭代器(按适当顺序) |
4.ArrayList类:
长度可变的数组,允许所有对元素进行快速随机访问,允许有null,ArrayList线程不同步,向ArrayList中插入和删除元素速度较慢。
ListIterator只有在List集合中有,才可以使用进行迭代。
hasPrevious()如果以逆向遍历列表,列表迭代器有多个元素,则返回 true
previous() 返回列表中的前一个元素
set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)
public class ArrayListDemo1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List allList=new ArrayList();
allList.add("hello"); //增加元素,Collection接口定义
allList.add(0, "hehe");//增加元素,List接口定义
allList.add("world");//增加元素,Collection接口定义
allList.add(3);
allList.add(5);
System.out.println(allList);
allList.remove(2);
//allList.remove("hehe"); //删除对象元素
System.out.println(allList);
for(int i=0;i<allList.size();i++)
{
System.out.println(allList.get(i));
}System.out.println("***************");
List allList1=new ArrayList();
allList1.add("hello"); //增加元素,Collection接口定义
allList1.add("hehe");//增加元素,Collection接口定义
allList1.add("world");//增加元素,Collection接口定义
allList1.add("hehe");
allList1.add(3);
allList1.add(5);
System.out.println(allList1);
allList1.remove("world");
//allList.remove("hehe"); //删除对象元素
System.out.println(allList1);
Object obj[] =allList1.toArray(); // 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
for(int i=0;i<obj.length;i++)
{
System.out.println(obj[i]);
}
System.out.println("判断某个字段是否存在:"+allList.contains("world"));
System.out.println("得到元素第一次出现的位置"+allList1.indexOf("hehe"));
System.out.println("得到元素最后一次出现的位置"+allList1.lastIndexOf("hehe"));
System.out.println("查询其中第几条到第几条的数据:"+allList.subList(0,3 ));//下标从0到2的数据取出,而不包含3
ListIterator<String> iter=allList1.listIterator(); //ListIterator只有List集合中有
while(iter.hasNext()){
Object str=iter.next();
System.out.println(str);
}
while(iter.hasPrevious())
{
//要想执行由后向前的操作,必须先执行由前向后的操作!!
//可以直接进行修改
System.out.println("从后向前输出:"+(Object)iter.previous()+"、");
}
}
}
4. LinkedList类:
LinkedList实现了List接口,允许null元素,在实现中采用链表数据结构。对顺序访问进行了优化,向List中插入和删除元素速度快,随机访问速度相对较慢,随机访问是指检索位于特定索引位置的元素。
LinkedList没有同步方法,如果多个线程同时访问一个List,则必须实现访问同步。
一种解决方式是创建List时构造一个同步的List:
List list=Collection.synchronizedList(new List(…));
public class LinkedListDemo1{
/**
* @param args
* LinekedList可以进行向前和向后查询表,但前提是先向后进行扫,而后才可以用向前扫的方式
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedList<String> link=new LinkedList<String>();
link.add("hehe");
link.add("haha");
link.addFirst("我了个去!!");
link.addLast("你了个去哪??");
for(int i=0;i<link.size();i++)
{
// System.out.println(link.get(i));
System.out.print(link.element()); //取出表头循环输出
}
System.out.println("\n通过element操作之后"+link);
for(int i=0;i<link.size();i++)
{
System.out.print(link.poll()); //取出表头同时删除表头
}
System.out.println("\n通过poll操作之后"+link);
//System.out.println("取出链表头:"+link.getFirst());
//System.out.println("取出链表尾:"+link.getLast());
}
}
}
}
Map接口:
Map(映射)是一种把键对象和值对象进行映射的集合,它的每一个元素都包含一对键对象和值对象,而值对象仍可以是Map类型。这样可以形成多级映射。
HashMap类:
按照哈希算法存取Map中的对象,允许存储为空,而且键是空。
public class HashMapDemo {
/**
* @param args
*/
private static Random rand=new Random();
public static void main(String[] args) {
// TODO Auto-generated method stub
Map hm=new HashMap();
for(int i=0;i<1000;i+=1){
Integer r=new Integer(rand.nextInt(20));
if(hm.containsKey(r))
((Counter)hm.get(r)).i++;
else
hm.put(r,new Counter());
}
System.out.println(hm);
}
}
class Counter{
int i=1;
public String toString(){
return Integer.toString(i);
}
}
HashTable类:
Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可以作为key或者value。
public class HashTableDemo {
/**
* Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可以作为key或者value。
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String names[]={"张三","李四","王五","赵六","陈七","孙九"};
float diameters[]={4800f,12103.6f,12756.3f,6794f,142984f,120536f};
Hashtable hash=new Hashtable();
for(int i=0,n=names.length;i<n;i++){
hash.put(names[i],new Float(diameters[i]));
}
Enumeration e=hash.keys(); //返回此哈希表中的键的枚举
Object obj;
while(e.hasMoreElements()){
obj=e.nextElement();
System.out.println(obj+":"+hash.get(obj));
}
}
}
HashMap和HashTable的区别:
HashTable继承自Dictionary,而HashMap是Map接口的一个实现 HashMap允许将null作为一个key或者value,而HashTable不允许。HashMap把HashTable的contains方法去掉了,才成containsvalue和containsKey。 最大的不同是,HashTable的方法是synchronize的,而HashMap不是,在多个线程访问HashTable时,不需要自己为它的方法实现同步而HashMap就必须为之提供外同步。
ArrayList和Vector的区别:
ArrayList与Vector都是java中集合类,区别:
同步性:Vector是同步的,这个类中的一些方法保证了Vector中的对象时线程安全的,ArrayList是异步的,同步的要求会影响执行的效率,如果对安全性要求不是那么高,使用ArrayList是很好的选择,可以避免同步带来的不必要的性能开销。
数据增长:从内部实现机制来讲,ArrayList和Vector都是使用数组(Array)来控制集合中的对象,当在添加数目的时候,如果超过内部数组的长度,在扩展内部数组长度时,Vector缺省情况下自动增长为一倍的数组长度,ArrayList增长原来的50%,要想保存大量数据,Vector更有优势。
集合选取的一般方式:
如果线程安全:使用Vector、HashTable
如果不要求线程安全:ArrayList LinkedList HashMap
要求使用键值对:HashMap HashTable
大数据量又考虑线程安全,使用Vector。