1  集合

1.1  集合概述

    集合是用来存储对象,并对多个对象进行操作的容器。

    集合和数组都可以存储对象,但集合长度是可变的,而数组长度是固定的。

    数组还可以存储基本数据类型,而集合只能存储对象。

    实际上存放的是对象的引用(内存地址)。

 

Java中的集合框架:


       

Collection接口有两个子接口:ListSet

 

Collection

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

        |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快,但是增删很慢。线程不同步

        |--LinkedList:底层使用的链表数据结构。特点:查询速度很慢,增删速度快。

        |--Vector:底层是数组数据结构。功能与ArrayList相同,但是线程同步。被ArrayList替代(多线程加锁)

    |--Set:元素是无序的,元素不可以重复。无序:存入和取出的顺序不一定一致。

        |--HashSet:数据结构是哈希表,线程是非同步的。保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals()方法,是否为true

        |--TreeSet:可以对Set集合中的元素进行排序,底层数据结构是二叉树。保证元素唯一性的依据:compareTo()方法的return 返回值是0,即: return 0;

 

1.2  集合Collection共性方法

    1boolean add(e)

        将指定的元素添加到此列表的尾部,即添加一个对象到集合尾部,e是要添加到此列表中的元素(任意类型),返回true

    2boolean remove(Object o)

        移除此列表中首次出现的指定元素(如果存在)。如果此列表包含指定的元素,则返回true

    3void clear()

        移除此列表中的所有元素。

    4int size()

        返回此列表中的元素数,即集合中对象的个数。

    5boolean contains(Object o)

        如果此列表中包含指定元素,则返回true,即如果此集合中包含o这个元素,则返回true

    6boolean isEmpty()

        如果此列表没有元素,返回true,即是个空的集合,返回true

    7boolean retainAll(Collection c)

        移除当前集合中未包含在集合c中的所有元素,取交集。如果当前集合因为调用发生更改,则返回true

    8boolean removeAll(Collection c)

        移除当前集合中,两个集合的交集,即去掉交集。如果当前集合因为调用发生更改,则返回true

    9boolean containsAll(Collection c)

        如果当前集合包含集合c中的所有元素,则返回true

    10boolean addAll(Collection c)

        将集合c添加到当前集合的尾部,如果当前集合因为调用发生更改,则返回true

 

1.3  迭代器Iterator

    什么是迭代器呢?

    其实就是集合的取出元素的方式,用来操作集合。

    Iterator<T> iterator();

    Iterator接口:把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素,那么取出方式就被定义成了内部类。

    而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容(判断和取出),把共性内容封装为Iterator接口。

    那么如何获取集合的取出对象呢? 通过一个对外提供的方法 iterator()

    Iterator it = collection.iterator();

    boolean hasNext();

    Object next();

    void remove();

 

     集合共性方法和迭代器示例:

import java.util.*;

class CollectionDemo{
	public static void main(String[] args){
		method_3();
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
	
	public static void method_1(){
		//创建一个集合容器,使用Collection接口的子类。ArrayList
		ArrayList al = new ArrayList();
		
		//1,添加元素
		al.add("java01"); //add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");
		
		//打印原集合
		sop(al);
		
				
		//3,删除元素
		al.remove("java02");
		al.clear(); //清空集合
		
		//4,判断元素
		sop("java03是否存在:"+al.contains("java03"));
		sop("集合是否为空:"+al.isEmpty());
		
		
		//2,获取个数,集合长度。
		sop("size=:"+al.size()); //集合的size()代替了length(),获取长度
		
		sop(al);
	}
	
	public static void method_2(){
		ArrayList al1 = new ArrayList();
		al1.add("java01");
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");
		
		ArrayList al2 = new ArrayList();
		al2.add("java03");
		al2.add("java04");
		al2.add("java05");
		al2.add("java06");
		
		al1.retainAll(al2); //取交集,al1中只会保留和al2中相同的元素。
		sop("al1:"+al1);
		sop("al2:"+al2);
	}
	
	public static void method_3(){  //迭代器
		ArrayList al3 = new ArrayList();
		al3.add("java01");
		al3.add("java02");
		al3.add("java03");
		al3.add("java04");
		
		Iterator it = al3.iterator();
		while(it.hasNext()){
			sop(it.next());
		}
		/* 节约内存的写法,循环结束 it对象即消亡
		for(Iterator it = al3.iterator(); it.hasNext(); ){
			sop(it.next());
		} */
	}
}

2  List集合

    ListCollection接口的一个子接口,List集合也是集合的一种。

 

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

        |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度快,但是增删很慢。线程不同步。

        |--LinkedList:底层使用的链表数据结构。特点:查询速度很慢,增删速度快。

        |--Vector:底层是数组数据结构。功能与ArrayList相同,但是线程同步。被ArrayList替代(多线程加锁)。

 

2.1  List集合的特有方法

    List集合特有方法:凡是可以操作脚标index的方法都是该体系特有的方法。

 

    增:

    add(index,element):在集合的index位置(脚标)添加元素。

    addAll(index,Collection):在集合的index位置(脚标)添加一个集合。

    删:

    remove(index):删除集合中位置index上的元素。

    改:

    set(index,element):修改集合index位置上的元素为element

    查:

    get(index):获取指定位置上的元素。

    subList(from,to):获取从from位置到(to-1)位置上的子集合,包括首不包括尾。

    listIterator():获取ListIterator迭代器,ListIteratorIterator的子接口,是List集合特有的迭代器。

 

2.2  List集合特有迭代器ListIterator

    List集合特有的迭代器,ListIteratorIterator的子接口。

    在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常:ConcurrentModificationException

    所以在迭代时,只能用迭代器的方法操作元素,可是Iterator的方法是有限的,只能对元素进行判断、取出、删除的操作。

    如果想要其他的操作如添加、修改等,就需要使用其子接口,ListIterator

    该接口只能通过List集合的listIterator方法获取。

 

     List集合特有方法的代码示例:

import java.util.*;
class ListDemo{
	public static void main(String[] args){
		method_ListIterator();
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
	
	public static void method(){
		ArrayList al1 = new ArrayList();  //创建集合容器
		al1.add("java01");  //添加元素
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");
		sop("原集合是:"+al1);
		
		al1.add(1,"java05"); //增:在指定位置添加元素
		al1.remove(2);  //删:删除指定位置的元素
		al1.set(2,"java007"); //改:修改元素
		sop(al1);
		
		sop("get(1):"+al1.get(1));//查:获取指定元素
		for(int x=0; x<al1.size(); x++){  //获取全部元素
			sop("al1("+x+"):"+al1.get(x));
		}
		for(Iterator it=al1.iterator(); it.hasNext(); ){  //迭代获取全部
			sop(it.next());
		}
		
		//通过indexOf()获取对象的位置
		sop("java007位置:"+al1.indexOf("java007"));
		List sub = al1.subList(1,3); //包括首,不包括尾
		sop("sub:"+sub);
	}
	
	public static void method_Iterator(){
		ArrayList al2 = new ArrayList();  //创建集合容器
		al2.add("java01");  //添加元素
		al2.add("java02");
		al2.add("java03");
		sop("原集合是:"+al2);
		
		Iterator it = al2.iterator();
		while(it.hasNext()){
			Object obj = it.next();
			if(obj.equals("java02"))
				//al2.add("java08");  并发异常,集合和迭代器不能同时操作
				it.remove(); //将java02的引用从集合中删除了,但对象还在内存中
			sop("obj="+obj);
		}
		sop(al2);
	}
	
	public static void method_ListIterator(){
		ArrayList al3 = new ArrayList();  //创建集合容器
		al3.add("java01");  //添加元素
		al3.add("java02");
		al3.add("java03");
		sop("原集合是:"+al3);
		
		ListIterator li = al3.listIterator(); //获取ListIterator迭代器。
		while(li.hasNext()){
			Object obj = li.next();
			if(obj.equals("java02"))
				li.add("java008"); //set,remove
		}
		sop(al3);
	}
}

2.3  ArrayList集合

     ArrayList集合底层的数据结构使用的是数组结构。

     特点:查询速度快,但是增删很慢。

     ArrayList是线程不同步。

     ArrayList拥有Collection集合中的共性方法,以及List集合的特有方法。

 

     代码示例可以参考本文第一段代码Demo

 

2.4  Vector集合

     Vector类是List接口的子类,当然也实现了集合Collection接口。

     Vector集合的底层数据结构是数组。功能与ArrayList相同,但是Vector线程同步。

     可以被ArrayList替代(多线程加锁后)。

 

     Vector中的枚举:

     枚举就是Vector特有的取出方式。

     枚举和迭代器很像,其实枚举和迭代器是一样的。

     因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。

     (优先考虑Iterator接口,而不是Enumeration。)

 

     Vector代码示例:

import java.util.*;
class VectorDemo{
	public static void main(String[] args){
		Vector v = new Vector();
		v.add("java01");
		v.add("java02");
		v.add("java03");
		v.add("java04");
		
		Enumeration en = v.elements();  //Vector的elements方法返回一个枚举
		while(en.hasMoreElements()){  //hasMoreElements是否有更多元素
			System.out.println(en.nextElement()); //nextElement返回下一个元素
		}
	}
}

2.5  LinkedList集合

     LinkedList集合底层使用的是链表数据结构。

     特点:查询速度很慢,增删速度快。

     LinkedList集合特有方法:

          addFirst():在头部添加一个元素。

          addLast():在尾部添加一个元素。

 

          getFirst()get获取元素但不删除元素,获取列表第一个元素。

          getLast():获取列表末尾的元素。

          removeFirst():获取并且删除第一个元素。

          removeLast():获取并且删除最后一个元素。

          如果getremove时,列表为空没有元素,抛出NoSuchElementException异常。

 

     在JDK1.6中出现了替代方法(替代列表为空时抛出异常):

          offerFirst()offer替代了add,在此列表的开头插入指定的元素。

          offerLast():在此列表末尾插入指定的元素。

          peekFirst()peek替代了get,获取但不移除此列表的第一个元素;如果此列表为空,则返回 null

          peekLast():获取但不移除此列表的最后一个元素;如果此列表为空,则返回 nul

          pollFirst()poll替代了remove,获取并移除此列表的第一个元素;如果此列表为空,则返回 null

          pollLast():获取并移除此列表的最后一个元素;如果此列表为空,则返回 null

          如果peekpoll时,列表为空没有元素,不再抛出异常,而是返回null

 

LinkedList集合的代码示例:

import java.util.*;
class LinkedListDemo{
	public static void main(String[] args){
		LinkedList link = new LinkedList();
		link.addLast("java01");
		link.addLast("java02");
		link.addFirst("java03");
		link.addFirst("java04");
		sop(link);
		
		sop(link.getFirst());  //获取第一个元素
		sop(link.getLast());
		sop("size="+link.size());
		sop(link.removeFirst());  //获取并删除第一个元素
		sop("size="+link.size());
		
		while(!link.isEmpty()){  //使用LinkedList特有方法,相当于迭代器Iterator
			sop(link.removeFirst());
		}
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

3  集合的小练习

3.1  LinkedList集合的练习

     LinkedList集合的一个小练习,要求掌握。

     需求:使用LinkedList模拟一个堆栈或者队列数据结构。

     堆栈:先进后出。

     队列:先进先出。

 

     LinkedList练习的代码示例:

import java.util.*;
class LinkedListTest{
	public static void main(String[] args){
		DuiZhan d = new DuiZhan(); //堆栈
		d.myAdd("java01");
		d.myAdd("java02");
		d.myAdd("java03");
		d.myAdd("java04");
		sop(d);
		
		while(!d.isNull()){
			sop(d.myGet());
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

class DuiLie{  //模拟队列,先进先出。
	LinkedList link;
	DuiLie(){
		link = new LinkedList();
	}
	public void myAdd(Object obj){ //队列中在末尾添加元素。
		link.addLast(obj);
	}
	public Object myGet(){  //队列中在头部删除元素。
		return link.removeFirst();
	}
	public boolean isNull(){
		return link.isEmpty();
	}
}

class DuiZhan{  //模拟堆栈,先进后出。
	LinkedList link;
	DuiZhan(){
		link = new LinkedList();
	}
	public void myAdd(Object obj){  //堆栈中在末尾添加元素。
		link.addLast(obj);
	}
	public Object myGet(){    //堆栈中在末尾删除元素。
		return link.removeLast(); //这里与队列不同
	}
	public boolean isNull(){
		return link.isEmpty();
	}
}

3.2  ArrayList集合的练习1

     需求:去除ArrayList集合中的重复元素。

     死路:定义一个新集合,遍历原集合的元素,如果新集合中没有此元素,则不重复,添加。如果新集合中已有此元素,则重复,不添加。

 

     代码示例:

import java.util.*;
class ArrayListTest{
	public static void main(String[] args){
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java02");
		al.add("java03");
		sop(al);
		
		al = singleElement(al); //去除重复元素
		sop(al);
		
		Iterator it = al.iterator();  //迭代循环中next调用一次,就要hasNext判断一次。
		while(it.hasNext()){
			sop(it.next());
			//sop(it.next()+"..."+it.next()); //不能一次循环调用两次next();
		}
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
	
	public static ArrayList singleElement(ArrayList al){  //实现功能:去除重复元素
		ArrayList newAl = new ArrayList();  //定义一个临时容器,存储结果集合
		
		/* 如果新集合中没有此元素,则不重复,添加。
		如果新集合中已有此元素,则重复,不添加。 */
		Iterator it = al.iterator();
		while(it.hasNext()){
			Object obj = it.next();
			if(!newAl.contains(obj))
				newAl.add(obj);
		}
		return newAl;
		
	}
}

3.3  ArrayList集合的练习2

     需求:将自定义对象作为元素存到ArrayList集合中,并去除重复元素。

     比如:存人对象。同姓名同年龄,视为同一个人,为重复元素。

     思路:

     1,对人进行描述,将数据封装进人对象。

     2,定义容器,将人存入。

     3,取出。

 

     注意:List集合判断元素是否相同,依据是元素的equals()方法,即Object父类的equals()方法,有时需要重写equals(),contains()remove()都依赖equals()方法。

 

     代码示例(主要集合中的多态:add()中添加的是Object类型,如果要用自定义方法,需向下转型):

import java.util.*;
class ArrayListTest2{
	public static void main(String[] args){
		ArrayList al = new ArrayList();
		al.add(new Person("lisi01",30)); //al.add(Object,obj); //Object obj = new Person("lisi01",30);
		al.add(new Person("lisi02",32));
		al.add(new Person("lisi02",32));
		al.add(new Person("lisi03",36));
		///sop(al);
		al = singleElement(al); //去除重复元素
		
		Iterator it = al.iterator();
		while(it.hasNext()){
			Object obj = it.next();
			Person p = (Person)obj;  //next得到的是Object类型,向下转型为Person,才能调用Person自定义方法
			
			sop(p.getName()+"..."+p.getAge());
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
	
	public static ArrayList singleElement(ArrayList al){  //实现功能:去除重复元素
		ArrayList newAl = new ArrayList();  //定义一个临时容器,存储结果集合
		
		Iterator it = al.iterator();
		while(it.hasNext()){
			Object obj = it.next();
			
			if(!newAl.contains(obj)) //Collection接口中contains()的原理就是equals();
				newAl.add(obj);
		}
		return newAl;
		
	}
}

class Person{
	private String name;
	private int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	public boolean equals(Object obj){  //重写equals(),自定义两个对象相同的规则,用来去重。
		if(!(obj instanceof Person))
			return false;
		Person p = (Person)obj;
		System.out.println(this.name+"..."+p.name);
		
		return this.name.equals(p.name) && this.age == p.age;
	}
}


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐