集合——List集合


集合类出现的原因

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

集合中存储的是对象所在堆内存中的地址值,数组也是如此。


数组和集合类的区别

数组虽然也可以存储对象,但长度是固定的;

集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。

集合类的特点

集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。


集合框架的构成及分类

为什么会出现这么多的容器呢?

因为每个容器对数据的存储方式不同,这个存储方式称之为:数据结构



Collection定义了集合框架的共性功能。

1,添加

boolean add(e);添加对象

boolean addAll(collection);添加传入的集合中的所有元素

2,删除

boolean remove(e);删除对象

boolean removeAll(collection);删除传入集合中的所有元素

void clear();清空集合

3,判断

boolean contains(e);判断是否包含该对象

boolean isEmpty();判断该集合是否为空

4,获取

Iterator iterator();迭代器:集合中取出元素的方式

int size();获取该集合中元素的个数

5,获取交集

boolean retainAll();

6,集合变数组

Object[] toArray();

代码示例:

/**
Collection方法演示
*/
import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{
		//用Collection子类ArrayList创建集合容器
		ArrayList al1 = new ArrayList();
		ArrayList al2 = new ArrayList();
		//添加元素
		al2.add("java01");
		al2.add("java02");
		al1.add("java01");
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");
		//删除元素
		al1.remove("java03");
		sop(al1);
		al1.removeAll(al2);
		sop(al1);
		//判断集合
		sop(al1.isEmpty());
		sop(al1.contains(al2));
		//获取
		sop(al1.size());
		Iterator it = al1.iterator();
		while (it.hasNext())
		{
			sop(it.next());
		}
		//取交集
		sop(al1.retainAll(al2));
		//集合变数组
		Object[] obj  = al2.toArray();
		for (int a = 0;a<al2.size() ;a++ )
		{
			sop(obj[a]);
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

迭代器Iterator的说明

JAVA中有多种容器,因为每种容器的数据结构不同,所以取出对象的动作细节也不同,他们各自都有自己的取出方式,这些取出方式被定义在集合的内部,所以这个取出方式可以直接访问集合内部的元素。这些取出方式都有共性的内容,判断和取出,被定义在集合中的内部类都符合一个规则,该规则就是Iterator,内部类对外提供了一个公共的方法iterator();

举例说明:

电玩城里面抓娃娃的机器,装娃娃的箱子相当于是一个容器,里面的娃娃就是一个个对象,箱子里面抓娃娃的夹子就是迭代器,他被封装在容器的内部,外面的操纵杆是对外暴露的方法



Iterator的两种方式

/**
Iterator的两种定义方式
*/
import java.util.*;
class IteratorDemo 
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		get1(al);
		get2(al);
	}
	//方式一: while循环
	public static void get1(ArrayList al)
	{
		Iterator it = al.iterator();
		while (it.hasNext())
		{
			sop(it.next());
		}
	}
	//方式二:for循环,使用这种结构,节省内存
	public static void get2(ArrayList al)
	{
		for (Iterator it = al.iterator();it.hasNext() ; )
		{
			sop(it.next());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

Collection集合体系

Collection

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

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

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

|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。

数组结构和链表数据结构说明

数组数据结构

查询块,是因为该数据结构中每个元素都有指定的角标记录,只要知道这角标就可以查到该元素;

增删慢,是因为每加入一个元素,其后面的元素都要向后面移动位置

图示:


链表数据结构

增删块,是因为该数据结构中每个元素都记住它前面的一个元素。删除元素时,数据结构中其实是这样的操作,断开这个元素指向的前一个元素,再断开它后面指向它的元素,最后将它后面的元素指向它前面的元素即可;

查询慢,是因为该数据结构中的元素只知道它前面的元素,除非你找到与之关联的元素,否则就要一直找下去

图示:


List特有的方法:凡是可以操作角标的方法都是该体系特有的方法

add();addAll(index,collection);

remove(index);

set(index,element);

get(index);subList(from,to);int indexOf(obj);ListIterator();

ListIterator()说明:

List集合特有的迭代器。ListIterator是Iterator的子接口。在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。

ListIterator接口的特有方法

Boolean  hasPrevious():

逆向遍历元素,和hasNext()方法相反

int  nextIndex() 

          返回对 next 的后续调用所返回元素的索引。 

E  previous() 

          返回列表中的前一个元素。 

int  previousIndex() 

          返回对 previous 的后续调用所返回元素的索引。 

void  remove() 

          从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。 

void  set(E e) 

          用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。 

代码示例:

/**
List集合的特有方法演示
*/
import java.util.*;
class ListDemo 
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		//添加元素
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		al.add("java05");
		print(al);
		//删除元素
		al.remove(2);
		sop(al);
		//修改元素
		al.set(2,"java02");
		sop(al);
		get(al);
		
	}
	//获取元素
	//方式一
	public static void print(ArrayList al)
	{
		for (int a = 0;a<al.size() ;a++ )
		{
			sop("al"+a+"="+al.get(a));
		}
	}
	//方式二
	public static void get(ArrayList al)
	{
		ListIterator li = al.listIterator();//list集合特有的迭代器
		while (li.hasNext())
		{
			sop(li.next());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}


枚举

枚举是vector特有的取出方式;

其中的Enumeration和Iterator用法一致;

Vector和ArrayList的区别也就在此,Vector支持枚举。


代码示例:

/**
Enumeration演示
*/
import java.util.*;
class EnumerationDemo 
{
	public static void main(String[] args) 
	{
		Vector v = new Vector();
		v.add("java01");
		v.add("java02");
		v.add("java03");
		v.add("java04");
		v.add("java05");
		enumeration(v);
	}
	public static void enumeration(Vector v)
	{
		for (Enumeration en = v.elements();en.hasMoreElements() ; )
		{
			System.out.println(en.nextElement());
		}
	}
}

LinkedList的特有方法

addFirst();在所有元素的最前面添加元素

addLast();在所有元素的最后面添加元素


getFirst();获取第一个位置的元素

getLast();获取最后一个位置的元素

获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException


removeFirst();获取第一个元素,并删除掉此元素

removeLast();获取最后一个元素,并删除掉此元素

获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException


在JDK1.6出现了替代方法。
以后使用这些方法


offerFirst();在集合的开头插入元素

offerLast();在集合的最后插入元素


peekFirst();

peekLast();

获取元素,但不删除元素。如果集合中没有元素,会返回null。


pollFirst();

pollLast();

获取元素,但是元素被删除。如果集合中没有元素,会返回null。

代码示例:

/**
LinkedList特有方法演示
*/
import java.util.*;
class LinkedListDemo 
{
	public static void main(String[] args) 
	{
		LinkedList link = new LinkedList();
		link.addFirst("java01");
		link.addFirst("java02");
		link.addFirst("java03");
		link.addFirst("java04");
		sop(link);
		link.addLast("java01");
		link.addLast("java02");
		link.addLast("java03");
		link.addLast("java04");
		sop(link);
		sop(link.getFirst());
		sop(link.getLast());
		sop(link.removeFirst());
		sop(link.removeLast());
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	
	}
}

JDK1.6版本

/**
LinkedListJDK1.6 特有方法演示
*/
import java.util.*;
class LinkedListDemo 
{
	public static void main(String[] args) 
	{
		LinkedList link = new LinkedList();
		link.offerFirst("java01");
		link.offerFirst("java02");
		link.offerFirst("java03");
		link.offerFirst("java04");
		sop(link);
		link.offerLast("java01");
		link.offerLast("java02");
		link.offerLast("java03");
		link.offerLast("java04");
		sop(link);
		sop(link.peekFirst());
		sop(link.peekLast());
		sop(link.pollFirst());
		sop(link.pollLast());
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	
	}
}

练习总结:

练习一

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

/**
使用LinkedList模拟一个堆栈或者队列数据结构。

堆栈:先进后出  如同一个杯子。
队列:先进先出 First in First out  FIFO 如同一个水管。
*/
import java.util.*;
/*
此类将linkedList方法封装进我们自己创建的对象中;
实际开发中这种用法非常多见
*/
class DuiLie
{
	private LinkedList link;
	DuiLie()
	{
		link = new LinkedList();
	}
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
	/*
	将此处的removeLast改成removeFirst方法,
	就是先进后出的,堆栈数据结构
	*/
	public Object myGet()
	{
		return link.removeLast();
	}
	public boolean isNull()
	{
		return link.isEmpty();
	}
}
class DuiLieTest 
{
	public static void main(String[] args) 
	{
		DuiLie dl = new DuiLie();
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");
		while (!(dl.isNull()))
		{
			System.out.println(dl.myGet());
		}

	}
}

总结:

练习一可以直接使用LinkedList集合完成,但实际开发中,这种方法并不适用。实际开发中,都是将其封装起来,定义我们自己的名称,对外暴露自己设定的方法,增强通用性。

这一思想非常重要


练习二:

删除集合中的重复元素

/**
需求:删除ArrayList集合中的重复元素
分析:
1,建立一个临时容器,先放入一个元素
2,放入之后每放入一个元素就和其中的元素记性比较,如果相同则不存入,否则存入
3,输出该集合
步骤:
1,临时容器al,放入元素al.add();
2,遍历容器中的数组:Iterator(),判断元素是否存在:contains(),不同存入add()
3,sop(al)
*/
import java.util.*;
class RemoveRepeatTest 
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java02");
		al.add("java01");
		sop(al);//输出al集合中的元素
		al = removeRepeat(al);//删除集合al中的重复元素
		sop(al);//输出取出重复元素后的集合
	}
	public static ArrayList removeRepeat(ArrayList al)
	{
		ArrayList newAl = new ArrayList();//建立临时容器,用于存储未重复的元素
		/*
		遍历集合al中的元素,将元素存入临时容器newAl中,判断临时容器中是否有该元素,
		如果没有就存入。
		注意:一个hasNext()只能对应一个next();
		*/
		for (Iterator it = al.iterator();it.hasNext() ; )
		{
			Object obj = it.next();//一个hasNext()只能对应一个next(),所以设置一个引用类型变量进行存储
			if (!(newAl.contains(obj)))//判断这个集合中是否包含这个元素
			{
				newAl.add(obj);
			}
		}
		return newAl;
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}


练习三:

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

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

比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。
思路:
1,存储元素
2,删除重复元素
3,输出元素
步骤:
1.定义Person类,该类中具有getName方法和getAge方法,复写equals方法
2.定义一个临时容器,用于存储未重复的元素,判断临时容器中是否包含该元素,不包含则存储,否则不存储
3,输出临时容器
*/
import java.util.*;
class MyTest 
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		/*
		这里有一个自动向上转型的过程,Person对象向上转型为object对象
		因为add()方法中添加的是object对象,这里存入person对象,相当于
		Object obj = new Person("zhangsan01",11);
		父类引用指向子类对象,多态的表现
		*/
		al.add(new Person("zhangsan01",11));
		al.add(new Person("lisi01",22));
		al.add(new Person("zhangsan02",22));
		al.add(new Person("lisi01",22));
		al.add(new Person("zhangsan03",43));
		al = removeRepeat(al);
		iterator(al);
	}
	//遍历集合中的对象,
	public static void iterator(ArrayList al)
	{
		for (Iterator it = al.iterator();it.hasNext() ; )
		{
			/*
			it.next()中取出的是Object对象,要对person进行操作,
			需要将Object对象强制转换成Person对象
			*/
			Person p = (Person)it.next();
			sop(p.getName()+"::"+p.getAge());
		}
	}
	//判断临时容器中是否存在相同的元素,不同的存储 ,相同的不进行存储
	public static ArrayList removeRepeat(ArrayList al)
	{
		ArrayList newAl = new ArrayList();
		for (Iterator it = al.iterator();it.hasNext(); )
		{
			Object obj = it.next();
			/*
			注意:contains()方法底层调用的方法是equals()方法
			在执行contains方法时,默认调用equals方法
			*/
			if (!(newAl.contains(obj)))
			{
				newAl.add(obj);
			}
		}
		return newAl;
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	/*
	Object中的equals比较的是对象的地址值,这里覆写对象的equals方法,
	使其具备判断对象的姓名和年龄是否相同的功能
	*/
	public boolean equals(Object obj)
	{
		//不包含就不进行判断
		if (!(obj instanceof Person))
		{
			return false;
		}
		Person p = (Person)obj;//Object对象强转成Person对象
		return this.name.equals(p.name) && this.age == p.age;
	}
	public String getName()//该方法主要用于迭代集合中对象的内容时,被调用
	{
		return  name;
	}
	public int getAge()
	{
		return age;
	}
}


程序知识点总结:

1,存储元素和存储对象是两个不同的概念

对元素进行操作的过程相对较简单

对对象进行操作的过程中需要对对象进行强制转换,因为集合中涉及到的方法,传入的都是Object对象(例如add(Object obj)),所以,如果要对子类对象进行操作,需要将该对象进行强制向下转型;

2,contains()方法和remove()方法底层调用的都是equals()方法,这点非常重要;

这也是remove方法的返回值类型是Boolean型的原因



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值