API-集合框架-Collection

 
 
一、集合体系概述
 
1、为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
 
2、数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
 
3、集合类的特点
集合中存储的都是对象的引用(地址)。
 
4、集合框架 
为什么会出现这么多容器?
因为每一个容器对数据的存储方式不同。存储方式称之为:数据结构
 
Collection是集合框架中的根接口。其下有两个常用子接口:List(列表),Set(集)。
所属关系:Collection

 

                         |--List  //元素是有序的,元素可以重复。因为该集合体系有索引。

 

                         |--Set  //元素是无序的,元素不可以重复。
 
 
二、Collection的共性方法
 
1、添加元素
        add(Object obj); //add方法的参数类型是Object。以便于接收任意类型对象。

2、获取个数,集合长度
        size();
 
3、删除元素
        remove(Object obj);
        clear();//清空集合

4、判断元素
        contains(Object obj);//判断是否存在obj这个元素
        isEmpty();//是否为空

5、取交集
        retainAll(另一集合);//调用者只保留两集合的共性元素。
 
6、获取元素
        迭代器:Iterator--其实就是集合的取出元素的方式。
        方法:hasNext();//如果仍有元素可以迭代,返回true。
                   next();//返回迭代的下一个元素。
                   remove();//移除最后一个元素。
        方式一:  Iterator it = al2.iterator();//获取迭代器,用于取出集合中的元素。         while (it.hasNext())         {     sop("al2:"+it.next());         }
方式二: for (Iterator it = al2.iterator(); it.hasNext(); )
        {
    sop("al2:"+it.next());
        }
        注意:在迭代式循环中next调用一次,就要hasNext判断一次。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
1,add方法的参数类型是Object。以便于接收任意类型对象。
2,集合中存储的都是对象的引用(地址)。
3,迭代器:其实就是集合的取出元素的方式。
*/
classCollectionDemo
{
publicstaticvoid main(String[] args)
{
//创建一个集合容器。使用Collection接口的子类。ArrayList
ArrayList al1 =newArrayList();
ArrayList al2 =newArrayList();
 
//1、添加元素。
		al1.add("java01");//add(Object obj);
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");
 
		al2.add("java01");//add(Object obj);
		al2.add("java02");
		al2.add("java05");
		al2.add("java06");
 
 
//打印集合
		sop("原集合al1:"+al1);
 
//2、获取个数。集合长度。
		sop("al1:size = "+al1.size());
 
//3、删除元素
		al1.remove("java03");
 
//al.clear();//清空集合。
		sop("新集合al1:"+al1);
 
//4、判断元素。
		sop("java01是否存在于al1:"+al1.contains("java01"));
		sop("al1集合是否为空:"+al1.isEmpty());
 
//5、取交集。al1中只会保留al2中相同的元素。
		al1.retainAll(al2);
//al1.removeAll(al2);
		sop("al2"+al2);
		sop("al1与al2取交集后的al1:"+al1);
 
//获取元素
Iterator it = al2.iterator();//获取迭代器,用于取出集合中的元素。
while(it.hasNext())
{
			sop("al2:"+it.next());
}
/*for (Iterator it = al2.iterator(); it.hasNext(); )
		{
			sop("al2:"+it.next());
		}*/
}
 
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
运行结果:
 
 
三、List
 
1、 List:元素是有序的,元素可以重复。因为该集合体系有索引。
         |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
         |--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
         |--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
 
2、List特有方法:凡是可以操作角标的方法都是该体系特有的方法。
a.增:add(index,element);
b.删:remove(index);
c.改:set(index,element);
d.查:get(index);
          subList(from,to);
          listIterator();
ListIterator:List集合特有的迭代器,是Iterator的子接口    
ListIterator特有的方法:
        add(obj);//增加
        set(obj);//修改为obj
        hasPrevious();//判断前面有没有元素
        previous();//取前一个元素
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">/*
Collection
     |--List:元素是有序的,元素可以重复。因为该集合体系有索引。
	 |--Set:元素是无序的,元素不可以重复。因为该集合体系没有索引。
List:
特有方法:凡是可以操作角标的方法都是该体系特有的方法。
 
增:add(index,element);
   add(index,Collection);
 
删:remove(index);
 
改:set(index,element);
 
查:get(index);
   subList(from,to);
   listIterator();
 
List集合特有的迭代器:ListIterator是Iterator的子接口
ListIterator特有的方法:
        add(obj);//增加
        set(obj);//修改
        hasPrevious();//判断前面有没有元素
        previous();//取前一个元素
*/
import java.util.*;
classListDemo
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();
 
//添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
 
//打印集合
		sop("原集合al:"+al);
 
//在指定位置添加元素
		al.add(1,"java08");
		sop("在指定位置1添加元素:"+al);
 
//删除指定位置元素
		al.remove(2);
		sop("删除指定位置2元素:"+al);
 
//修改指定位置元素。
		al.set(2,"java05");
		sop("修改指定位置2元素:"+al);
 
//通过角标获取元素
		sop("通过角标获取元素get(1):"+al.get(1));
 
//通过角标遍历所有元素
		sop("遍历获取所有元素:");
for(int x=0; x<al.size(); x++)
{
			sop("al("+x+")="+al.get(x));
}
//通过indexOf获取对象的位置
		sop("index="+al.indexOf("java05"));
 
//返回子列表
List sub  = al.subList(1,3);
		sop("sub="+sub);
 
//演示列表迭代器
Iterator it = al.iterator();
while(it.hasNext())
{
//sop("al:"+it.next());
Object obj = it.next();
if(obj.equals("java01"))
//al.add("java009");//发生ConcurrentModificationException异常。
				it.remove();//Iterator方法有限,只有hasNext(); next(); remove();方法
}
		sop(al);
//如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。该接口只能通过List集合的ListIterator方法获取。
ListIterator li = al.listIterator();
while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("java05"))
				li.add("java09");//添加
}
		sop(al);
while(li.hasPrevious())//向前逆向遍历
{
Object obj = li.previous();//取前一个元素
if(obj.equals("java09"))
				li.set("java0007");//修改
}
		sop(al);
 
 
}
 
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
运行结果:
 
3、ArrayList
ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
例:去除ArrayList集合中的重复元素。
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
去除ArrayListTest集合中的重复元素
*/
classArrayListTest
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();
 
//添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java02");
		al.add("java03");
		al.add("java03");
		sop(al);
		al = singleElement(al);
		sop(al);
}
 
publicstaticArrayList singleElement(ArrayList al)
{
//定义一个临时容器
ArrayList newAl =newArrayList();
 
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(!newAl.contains(obj))
{
				newAl.add(obj);
}
}
return newAl;
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
运行结果:
 
例:将自定义对象作为元素存到ArrayList集合中,并去除重复元素。如存人对象,同姓名同年龄视为同一个人。
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
将自定义对象作为元素存到ArrayList集合中,并去除重复元素。如存人对象,同姓名同年龄视为同一个人
List集合判断元素是否相同,依据是元素的equals方法。
contains 底层调用的是equals方法,所以要重写equals方法。
*/
 
classPerson
{
privateString name;
privateint age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
publicboolean equals(Object obj)
{
if(!(obj instanceofPerson))
returnfalse;
Person p =(Person)obj;
//System.out.println(this.name+"..."+p.name);
returnthis.name.equals(p.name)&&this.age == p.age;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classArrayListTest1
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();
 
		al.add(newPerson("lisi01",11));//al.add(Object obj);//Object obj = new Person("lisi01",11);
		al.add(newPerson("lisi02",12));
		al.add(newPerson("lisi02",12));
		al.add(newPerson("lisi03",13));
		al.add(newPerson("lisi04",14));
		al.add(newPerson("lisi04",14));
		sop("原ArrayList集合:");
		printAl(al);
		al = singleElement(al);
		sop("新ArrayList集合:");
		printAl(al);
}
 
publicstaticvoid printAl(ArrayList al)
{
Iterator it = al.iterator();
while(it.hasNext())
{
//Object obj = it.next();  
Person p =(Person)it.next();
				sop(p.getName()+"::"+p.getAge());
}
}
 
publicstaticArrayList singleElement(ArrayList al)
{
//定义一个临时容器
ArrayList newAl =newArrayList();
 
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(!newAl.contains(obj))
{
				newAl.add(obj);
}
}
return newAl;
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
运行结果:
 
4、LinkedList
LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
LinkedList特有方法:
                                                                      在JDK1.6以后,出现了替代方法。
addFirst();                                                        offFirst();
addLast();                                                        offLast();
 
getFirst();                                                         peekFirst();
getLast();                                                         peekLast();
获取元素,但不删除元素。                              获取元素,但不删除元素。
如果集合中没有元素,                                     如果集合中没有元素,
会出现NoSuchElementException。              会返回null。
 
removeFirst();                                                  pollFirst();
removeLast();                                                  pollLast();
获取元素,并删除元素。                                  获取元素,并删除元素。 
如果集合中没有元素                                         如果集合中没有元素,
会出现NoSuchElementException。               会返回null。
例:  使用LinkedList模拟一个堆栈或者队列数据结构。
 
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
使用LinkedList模拟一个堆栈或者队列数据结构。 
堆栈:先进后出  如同一个杯子。 
队列:先进先出 First in First out  FIFO 如同一个水管。 
 
 
*/
classDuiLie
{
privateLinkedList link;
DuiLie()
{
		link =newLinkedList();
}
publicvoid myAdd(Object obj)
{
		link.addFirst(obj);
}
publicObject myGet()
{
return link.removeLast();//return link.removeFirst();就是堆栈
}
publicboolean isNull()
{
return link.isEmpty();
}
 
 
}
classLinkedListDemo
{
publicstaticvoid main(String[] args)
{
DuiLie dl =newDuiLie();
 
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");
while(!dl.isNull())
{
			sop(dl.myGet());
}
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}<span style="font-family: 'Microsoft YaHei'; color: rgb(190, 190, 197);"> </span></span>
 
5、Vector
Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
枚举就是Vector特有的取出方式
*/
classVectorDemo
{
publicstaticvoid main(String[] args)
{
Vector v =newVector();
 
		v.add("java01");
		v.add("java02");
		v.add("java03");
		v.add("java04");
 
Enumeration en = v.elements();
while(en.hasMoreElements())
{
System.out.println(en.nextElement());
}
}
}</span>
运行结果:
 
 
四、Set
 
1、Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。     
        |--HashSet:底层数据结构是哈希表。线程不同步。保证元素唯一性的依据:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。 
        |--TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0。
    
2、Set集合的功能和Collection是一致的。
 
3、HashSet
HashSet:底层数据结构是哈希表。线程不同步。
保证元素唯一性的依据:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。
注意:对于判断元素是否存在contains,以及删除remove等操作,依赖的方法是元素的hashcode和equals方法。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
将自定义对象作为元素存到HashSet集合中,并去除重复元素。如存人对象,同姓名同年龄视为同一个人
保证元素唯一性的依据:判断元素的hashCode值是否相同。
如果相同,还会继续判断元素的equals方法,是否为true。
注意:对于判断元素是否存在contains,以及删除remove等操作,依赖的方法是元素的hashcode和equals方法。
*/
 
classPerson
{
privateString name;
privateint age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
publicint hashCode()//重写hashcode
{
System.out.println(this.name+"...hashcode");
return name.hashCode()+age*39;
}
publicboolean equals(Object obj)//重写equals
{
if(!(obj instanceofPerson))
returnfalse;
Person p =(Person)obj;
System.out.println(this.name+"..."+p.name);
returnthis.name.equals(p.name)&&this.age == p.age;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classHashSetDemo
{
publicstaticvoid main(String[] args)
{
HashSet hs =newHashSet();
 
		hs.add(newPerson("a1",11));
		hs.add(newPerson("a2",12));
		hs.add(newPerson("a3",13));
		hs.add(newPerson("a2",12));
 
		sop("a1:"+hs.contains(newPerson("a1",11)));
		sop("a3:"+hs.remove(newPerson("a3",13)));
 
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p =(Person)it.next();
			sop(p.getName()+"::"+p.getAge());
}
 
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
 
4、TreeSet
TreeSet:底层数据结构是二叉树。可以对Set集合中的元素进行排序。默认按照字母的自然排序。
保证元素唯一性的依据:compareTo方法return 0。
二叉树:
TreeSet排序的两种方式  
1)第一种排序方式:自然排序
        让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。
2)第二种方式:比较器
        当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
比较器构造方式:定义一个类,实现Comparator接口,覆盖compare方法。
当两种排序都存在时,以比较器为主。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
往TreeSet集合中存储自定义对象学生,并按照学生年龄进行排序。
排序时,当主要条件相同时,一定要判断一下次要条件。
*/
classStudentimplementsComparable//该接口强制让学生具备比较性
{
privateString name;
privateint age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
publicint compareTo(Object obj)//若想怎么存怎么取,只需返回1;倒序则返回-1即可。
{
if(!(obj instanceofStudent))
thrownewRuntimeException("不是学生对象");
Student s =(Student)obj;
 
//System.out.println(this.name+"...compareto"+s.name);
if(this.age>s.age)
return1;
if(this.age==s.age)
{
returnthis.name.compareTo(s.name);
}
return-1;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classTreeSetDemo
{
publicstaticvoid main(String[] args)
{
TreeSet ts =newTreeSet();
 
		ts.add(newStudent("lisi02",22));
		ts.add(newStudent("lisi07",20));
		ts.add(newStudent("lisi09",19));
        ts.add(newStudent("lisi08",19));
        ts.add(newStudent("lisi08",19));
 
 
Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu =(Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
}
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}
 
classMyCompareimplementsComparator//构造比较器
{
publicint compare(Object o1,Object o2)
{
Student s1 =(Student)o1;
Student s2 =(Student)o2;
 
int num = s1.getName().compareTo(s2.getName());
if(num==0)
{
return  s1.getAge()- s2.getAge();
}
return num;
}
}</span>
例:按照字符串长度排序
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
//按照字符串长度排序
classTreeSetTest
{
publicstaticvoid main(String[] args)
{
TreeSet ts =newTreeSet(newStrLenComparator());
		ts.add("abd");
		ts.add("cc");
		ts.add("z");
		ts.add("hahaha");
		ts.add("zdf");
 
Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
 
classStrLenComparatorimplementsComparator
{
publicint compare(Object o1,Object o2)
{
String s1 =(String)o1;
String s2 =(String)o2;
int num =newInteger(s1.length()).compareTo(newInteger(s2.length()));
if(num ==0)
return s1.compareTo(s2);
return num;
 
}
}</span>
运行结果:
 
 
五、泛型
 
1、泛型概述
泛型:JDK1.5版本以后出现的新特性。用于解决安全问题,是一个类型安全机制。
泛型格式:  通过<>来定义要操作的引用数据类型
好处:
a、将运行时期出现的问题ClassCastException,转移到了编译时期。方便于程序员解决问题。让运行时期的问题减少,安全。
b、避免了强制转化麻烦。
 
2、泛型使用
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,只要见到<>就要定义泛型。
其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
泛型:JDK1.5版本以后出现的新特性。用于解决安全问题,是一个类型安全机制。
好处:
1,将运行时期出现的问题ClassCastException,转移到了编译时期。方便于程序员解决问题。让运行时期的问题减少,安全。
2,避免了强制转化麻烦。
*/
classGenericDemo
{
publicstaticvoid main(String[] args)
{
ArrayList<String> al =newArrayList<String>();//当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
 
		al.add("abc01");
		al.add("abc002");
		al.add("abc0003");
//al.add(4);//编译通过,运行出现ClassCastException
 
Iterator<String> it = al.iterator();//当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
while(it.hasNext())
{
//String s = (String)it.next();//避免了强制转化麻烦。
String s = it.next();
System.out.println(s+"::"+s.length());
}
}
}</span>
运行结果:
运行结果中注意:使用了未经检查或不安全的操作的信息不见了。
 
3、泛型类、泛型方法、泛型接口
a.什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,
早期定义Object来完成扩展。现在定义泛型来完成扩展。
泛型类定义的泛型,在整个类中有效。在泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
b.为了让不同方法可以操作不同类型,而且类型还不确定。
那么可以将泛型定义在方法上。
c.特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">classDemo<T>//泛型类
{
publicvoid show(T t)
{
System.out.println("class show:"+t);
}
public<T>void print(T t)//泛型方法
{
System.out.println("function print:"+t);
}
publicstatic<T>void method(T t)//静态方法泛型
{
System.out.println("static method:"+t);
}
}
 
interfaceInter<T>//泛型接口
{
void show(T t);
}
 
classInterImpl<T>implementsInter<T>//泛型接口
{
publicvoid show(T t)
{
System.out.println("interface show:"+t);
}
}
 
 
classGenericDemo1
{
publicstaticvoid main(String[] args)
{
Demo<String> d =newDemo<String>();
Demo<Integer> d1 =newDemo<Integer>();
 
		d.show("haha");
		d1.show(0);
		d.print("hehe");
		d.print(newInteger(4));
		d.method("heihei");
		d.method(8);
 
 
InterImpl<String> i =newInterImpl<String>();
		i.show("hiahia");
InterImpl<Integer> i1 =newInterImpl<Integer>();
		i1.show(12);
}
}<span style="font-family: 'Microsoft YaHei'; color: rgb(190, 190, 197);"> </span></span>
运行结果:
 
4、泛型限定
?:通配符。也可以理解为占位符。
泛型的限定:
? extends E:可以接收E类型或E的子类型。上限。
?super E:可以接收E类型或E的父类型。下限。
代码示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
 
classGenericDemo2
{
publicstaticvoid main(String[] args)
{
ArrayList<Person> al =newArrayList<Person>();
		al.add(newPerson("abc01"));
		al.add(newPerson("abc002"));
		al.add(newPerson("abc0003"));
 
ArrayList<Student> al1 =newArrayList<Student>();
		al1.add(newStudent("abc---01"));
		al1.add(newStudent("abc---002"));
		al1.add(newStudent("abc---0003"));
 
		printColl(al);
		printColl(al1);
 
}
publicstaticvoid printColl(ArrayList<?extendsPerson> al)
{
Iterator<?extendsPerson> it = al.iterator();
while(it.hasNext())
{
System.out.println( it.next().getName());
}
}
 
}
 
classPerson
{
privateString name;
Person(String name)
{
this.name = name;
}
publicString getName()
{
return name;
}
}
 
classStudentextendsPerson
{
Student(String name)
{
super(name);
}
}</span>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章