黑马毕向东Java课程笔记(day14-1——14-11):集合类(集合框架)——集合类分类与特点+List集合接口及其子类

1、集合类特点
  为什么出现集合类?

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

  数组和集合类同是容器,有何不同?

  • 数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
    数组中可以存储基本数据类型,集合只能存储对象。(我们看到集合也可以存储基本数据类型是因为在向集合添加基本数据类型数据的时候会自动装箱)

  集合类的特点

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

2、集合类的分类
  集合类的框架:集合框架,集合框架的结构如下:
黑马毕向东Java课程笔记(day14-1——14-11):集合类(集合框架)——集合类分类与特点+List集合接口及其子类_第1张图片
黑马毕向东Java课程笔记(day14-1——14-11):集合类(集合框架)——集合类分类与特点+List集合接口及其子类_第2张图片
  Java集合框架主要包括两种类型的容器,一种是集合(Collection),另一种是图(Map)。Collection接口又有多个子接口,其中较为重要的是List、Set和Queue接口,再下面是一些抽象类,最后是具体实现类,常用的类有List——ArrayList、LinkedList、Vector,Set——HashSet(下面又有LinkedHashSet)、TreeSet;Map接口下面又有HashMap类(下面又有LinkedHashMap)、TreeMap类等。
  为什么会出现这么多的容器呢? 因为每一个容器(集合)对数据的存储方式都有不同,这个存储方式称之为:数据结构,既数据在内存中的存储方式。

3、集合框架Collection的共性方法
  Collection接口的共性方法,以ArrayList类为例。(视频14-2中有各类方法的粗略解读)

Collection定义了集合框架的共性功能。
1,添加
	add(e);
	addAll(collection);

2,删除
	remove(e);
	removeAll(collection);
	clear();

3,判断。
	contains(e);
	isEmpty();

4,获取
	iterator();
	size();

5,获取交集。
	retainAll();

6,集合变数组。
	toArray();

1、add方法的参数类型是Object。以便于接收任意类型对象。
2、集合中存储的都是对象的引用(地址),而不是对象实体!(见视频14-12,10.10开始的地方有解释)

什么是迭代器呢?
	其实就是集合的取出元素的方式,如同抓娃娃游戏机中的夹子。(视频14-3,6.42开始的迭代器的特点!)
	每一个集合的数据结构不同,导致他们的存取方式不同,而且一个集合取出方式不足以用一个方法来描述(取出要有判断有没有,取出等功能),  
	因此我们取出的多个功能封装到一个对象中,每个容器中都有一个取出对象,不同容器的取出对象的取出动作也不一样。为了描述取出对象,我们用一个类来描述取出方式。
该类定义在集合的内部,那么取出方式就被定义成了内部类,这样取出方式就可以直接访问集合内容的元素。

	而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容判断和取出,那么可以将写共性抽取。
那么这些内部类都符合一个规则,该规则抽取出来是接口Iterator,我们可以通过一个集合对外提供的方法iterator()方法来获取集合的取出对象,
该iterator()方法返回集合实现Iterator接口的内部类的对象(多态)(如AbstractList类中iterator()方法返回new Itr(),而Itr()类实现了Iterator接口并重写Iterator里面的方法,这些方法适用于AbstarctLIst的数据结构)。
这样我们就可以在集合外面,通过调用集合实现的接口Iterator的方法来调用集合的取出方法,而且针对不同集合的不同数据结构,不同集合对Iterator接口方法的实现方式不同。

	迭代器是取出方式,会直接访问集合中的元素,所以将迭代器通过内部类的形式来进行描述,通过容器的iterator()方法获取该内部类的对象。

  相应的代码示例如下:

package pack;

import java.util.*;//记得处理看java.lang包之外,其他包必须得手动导入。

class CollectionDemo 
{
	public static void main(String[] args) 
	{	
//		CollectionDemo.method_2();
		CollectionDemo.method_get();
	}
	
	//获取方法
	//iterator()方法,返回接口:Iterator iterator():返回按适当顺序在列表的元素上进行迭代的迭代器。
	public static void method_get()
	{
		ArrayList al = new ArrayList();	
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java04");
		//由于接口无法创建对象,接口型的引用只能指向它的子类对象(多态)
		//iterator()方法返回Iterator接口的子类对象(重写了Iterator接口的方法),这样就可以使用接口Iterator的方法
		Iterator it = al.iterator();//获取迭代器,用于取出集合中的元素
		while(it.hasNext())//hasNext():如果仍有元素可以获取
		{
			sop(it.next());//获取元素,next():返回迭代的下一个元素。
		}
		//运行结束it对象还在内存中
		//上面代码的规范写法
		for(Iterator it1 = al.iterator();it1.hasNext();)
		{
			sop(it1.next());
		}
		//运行结束for()循环结束,那么it1也会自动被清除
	}
	
	//获取集合交集的方法/移除集合交集方法
	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("java01");
		al2.add("java02");
		al2.add("java05");
		al2.add("java06");
		
//		al1.retainAll(al2);
//		sop(al1);//[java01, java02]:仅保留集合al1与al2的交集部分,并存储在al1中
//		sop(al2);//[java01, java02, java05, java06]
		//retainAll():仅在列表中保留指定 collection 中所包含的元素(可选操作)。
		
		al1.removeAll(al2);
		sop(al1);//[java03, java04]:移除集合al1与al2的交集部分,并将结果存储在al1中
		sop(al2);//[java01, java02, java05, java06]
		//从列表中移除指定 collection 中包含的其所有元素(可选操作)。
	}
	
	//基本方法
	public static void base_method()
	{
		//创建一个集合容器。使用Collection的子类ArrayList
		ArrayList al = new ArrayList();
				
		//添加元素
//集合只能存储对象,不能存储基本数据类型,而字符串就是一种对象(String类对象),其他基本数据类型也可以通过他们的包装类创建对象
		al.add("java02");
		al.add("java01");
		al.add("java03");
		al.add("java04");
				
		//打印原集合对象:会直接将集合的内容打印出来
		sop(al);//结果:[java01, java02, java03, java04]
				
		//删除元素
//		al.remove("java02");
//		al.clear();//清空集合
				
		//打印改变后的集合
//		sop(al);
				
		//获取集合长度
//		sop("size:"+al.size());
				
		//判断元素
		sop("java03是否存在:"+al.contains("java03"));
		sop("集合是否为空:"+al.isEmpty());
				
		//add(Object obj)(E e)是泛型,我们暂时理解为(Object obj),为什么使用Object obj
		//因为容器添加的对象是类类型的,所以只能使用上帝父类Object来作为参数(多态)
				
		//向集合中存储对象时内存的存储情况:14-12,10.10开始的地方有解释。集合存储的是对象在堆中的地址值。
	}
	
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

4、List集合的共性方法
  List集合的方法与特点如下

Collection
	|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
		|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
		|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
		|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。


	|--Set:元素是无序,元素不可以重复。、


List:特有方法。凡是可以操作角标的方法都是该体系特有的方法。而Set无序不重复,没有角标可以操作。

增
	add(index,element);
	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方法获取。

  相应的示例代码如下:

package pack;

import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{	
		//演示列表迭代器
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		
		sop("原集合:"+al);
		/*
		//在迭代过程中准备添加或者删除元素
		for(Iterator it = al.iterator(); it.hasNext();)
		{
			Object obj = it.next();
			if(obj.equals("java02"))
//				al.add("java0007");
				//那么我们只使用迭代器的方法
				it.remove();//将java02的引用从集合中删除了,集合中没有java02的引用,但是obj仍然指向相应的内存地址
			sop("obj="+obj);
//这里移除后仍然会打印“java02”,因此remove()只是移除了元素的引用it,而元素仍然在内存中,
//而obj之前通过it.next()指向内存中的地址,这个时候打印obj仍然会有内容。
		}
		//这一部抛出:java.util.ConcurrentModificationException(视频14-5,5.50处解释)
		//此处并发访问,我们在用迭代器的对象obj操作元素的时候,又用集合的方法al往同一组元素里面添加元素。
		//不可以既用集合又用迭代器同时操作同一组元素
		sop("操作后的集合:"+al);
		*/
		
		//上面的Iterator迭代器只能有3个动作,它的子接口ListIterator,它有指针,因此它的方法较多!
		ListIterator li = al.listIterator();
//		sop("hasNext():"+li.hasNext());//true
//		sop("hasPrevious():"+li.hasPrevious());//false
		while(li.hasNext())
		{
			Object obj = li.next();
			if(obj.equals("java02"))
//				li.add("java hha");
				li.set("hahah");
		}
		
		while(li.hasPrevious())
		{
			sop("pre:"+li.previous());//逆向获取
		}
//		sop("hasNext():"+li.hasNext());//false
//		sop("hasPrevious():"+li.hasPrevious());//true
		sop(al);
	}
	
	
	public static void method()
	{
		//由于List是接口无法创建对象,我们创建一个他的子类ArrayList的对象
		ArrayList al = new ArrayList();

		//添加元素
		al.add("java01");
		al.add("java02");
		al.add("java03");
		sop("原集合是:"+al);
		//在这个位置添加元素
		al.add(1, "java08");
		sop("添加后的集合是:"+al);
		//删除指定位置的元素
		al.remove(2);
		sop("删除后的集合是"+al);
		//修改元素
		al.set(2, "java haha");
		sop("修改后的集合是"+al);
				
		//通过角标获取元素
		sop("角标2的元素是:"+al.get(2));
		//获取所有的元素
		//由于List有下标且有序,我们首先可以使用for循环通过下标来索引
		for(int x=0; x<al.size(); x++)//注意,集合没有length()方法,想要获取集合的长度必须得使用size()方法
		{
			System.out.println("al("+x+")="+al.get(x));
		}
		//其次,同样可以使用迭代器来获取集合元素
		for(Iterator it = al.iterator(); it.hasNext();)
		{
			sop(it.next());
		}
				
		//通过indexOf获取对象的位置
		sop("java08的位置是:"+al.indexOf("java08"));
				
		//获取子列表,subList(int fromIndex,int toIndex),返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图
		//subList的返回值是List,因此这里创建List的对象,而不能是ArrayList
		List sub = al.subList(0, 2);
		sop("sub="+sub);
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

5、List集合常见的子类对象及其特点
  List集合常见的子类如下:(数组与链表数据结构的区别,见视频14-6,1.20处解释)

|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
		|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快(改查很快,查询到就可以修改)。但是增删稍慢。线程不同步。ArrayList长度默认为10,当我们添加的长度超过10,就会new一个新的数组,长度是15(50%延长),并将原来数组中的元素copy过来,再添加新元素。(可变长度数组)
		|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
		|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。(100%延长)

5.1、Vector类
  下面我们专门说一下Vector这个类,它里面有一些特殊的东西需要介绍(枚举Enumeration)

枚举就是Vector特有的取出方式,发现枚举和迭代器很像,其实枚举和迭代是一样的。

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

  相应的示例代码如下:

import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{	
		Vector vc = new Vector();
		vc.add("java01");
		vc.add("java02");
		vc.add("java03");
		vc.add("java04");
		
		//element()方法返回枚举接口Enumeration的对象(多态),类似于之前的迭代器
		Enumeration en = vc.elements();
		
		while(en.hasMoreElements())
		{
			sop(en.nextElement());
		}
	}
	
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

5.2、LinkedList类
  我们介绍一下LinkedList的特有方法

LinkedList:特有方法:
addFirst();
addLast();

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

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

在JDK1.6出现了替代方法。

offerFirst();
offerLast();

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

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

  相应的代码如下:

package pack;

import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{	
		LinkedList link = new LinkedList();
		//连续将4个指定元素插入链表的开头
		link.addFirst("java01");
		link.addFirst("java02");
		link.addFirst("java03");
		link.addFirst("java04");
		sop(link);//[java04, java03, java02, java01]:每次在开头插入一个,前面插入的往链表后面排
		
		LinkedList link1 = new LinkedList();
		//连续将4个指定元素插入链表的结尾
		link1.addLast("java01");
		link1.addLast("java02");
		link1.addLast("java03");
		link1.addLast("java04");
		sop(link1);//[java01, java02, java03, java04]:每次在结尾插入一个,前面插入的往链表前面排
		
		//获取元素,但不删除元素
		sop(link.getFirst());//java04
		sop(link.getLast());//java01
		sop("size="+link.size());//size=4:获取后链表长度不变
		
		//获取元素,但是元素被删除。注意LinkedLinkList的removeFirst()方法,它不但是移除,还有删除功能
//		sop(link.removeFirst());//java04:不仅仅是移除,还会获取
//		sop(link.removeLast());//java01
//		sop("size="+link.size());//size=2,移除后链表长度减小
		
		//将链表中的元素全部取出:不用迭代器
		while(!link.isEmpty())
		{
			sop(link.removeFirst());//我们取一个再删除一个,如果为空就结束循环
		}
		//当然也可以使用for循环判断长度,但是判断是否为空再移除的方法更加简单
		for(int x=0; x<link.size(); x++)
		{
			System.out.println(link.get(x));
		}
		
	}
	
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

  LinkList的练习如下:

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

堆栈:先进后出  如同一个杯子。
队列:先进先出 First in First out  FIFO 如同一个水管。
我们将LinkedList封装到堆栈/队列的类中,然后对外暴露堆栈/队列的相应方法,
使得外部通过创建堆栈/队列的对象可以调用相应的功能实现堆栈/队列的数据结构
*/
package pack;

import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{	//自己造一个容器,只不过该容器基于LinkedList容器
		Queue qe = new Queue();//创建Queue对象,并为LinkedList的引用赋予对象
		//先存
		qe.myAdd("java01");
		qe.myAdd("java02");
		qe.myAdd("java03");
		qe.myAdd("java04");
		//取出并移除,先进先出
		while(!qe.isNull())//不为空一直取出
		{
			System.out.println(qe.myRemove());
			//结果:先进先出
//			java01
//			java02
//			java03
//			java04
		}
	}
	
}

//描述队列数据结构的类
class Queue
{
	//首先创建一个LinkedList的引用,并在Queue的构造方法里面为其赋予对象
	//这样在创建Queue对象的时候就可以顺便为LinkedList的对象赋值,这样不创建Queue对象的时候就没有LinkedList对象,不占内存
	private LinkedList link;//创建一个私有的LinkedList对象
	Queue()
	{
		link = new LinkedList();
	}
		
	//添加的方法:在开头添加对象
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
	//获取并移除的方法:先进先出,那么移除末尾,并返回此移除对象
	public Object myRemove()
	{
		return link.removeLast();//先进先出,移除最后
	}
	//判断是否为空
	public boolean isNull()
	{
		return link.isEmpty();
	}
}
//堆栈与队列其实同理,只不过改成先进后出即可

5.3、ArraysList类
  ArrayList的练习1如下:

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

我们创建一个singleElement方法来实现该功能,在外部创建一个需要去除重复元素的ArrayList集合
我们将这个ArrayList的引用al传入singleElement,在singleElement中设置一个临时ArrayList集合(newAl),
用al创建迭代器取al集合中的元素,如果newAl集合中不包含某个元素,就将该元素存入newAl集合,singleElement返回newAl对象
这样就可以去除al中的重复元素
*/
package pack;

import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{	
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java03");
		al.add("java04");
		al.add("java02");
		sop("原集合为:"+al);
		
		al = singleElement(al);//将al集合传入singleElement方法去除重复元素再取出,返回一个去除了重复元素的ArrayList对象
		sop("去除重复元素后的集合为"+al);
		
		/*
		在迭代时循环中next调用一次,就要hasNext判断一次。在循环中放多个next()会容易出错
		Iterator it = al.iterator();

		while(it.hasNext())
		{
			sop(it.next()+"...."+it.next());
		}
		*/
	}
	
	//实现去除重复元素的方法:传入需要去除重复元素的ArrayList对象,返回新的ArrayList对象
	public static ArrayList singleElement(ArrayList al)
	{
		ArrayList newAl = new ArrayList();//创建一个新的ArrayList对象
		
		Iterator it = al.iterator();//使用构造器,来遍历获取集合al中的元素。先创建一个Iterator接口的子类对象it	
		//在循环中,用实现Iterator的内部类对象it调用hasNext()方法遍历集合al的所有对象
		while(it.hasNext())//如果al还有元素没有遍历到
		{
			Object obj = it.next();//使用Iterator接口的next()方法将al集合中的取出放到Object对象中
			if(!newAl.contains(obj))
				newAl.add(obj);//如果newAl这个集合中不包含obj,就将obj添加到newAl的集合中
		}
		return newAl;//newAl就是取出重复元素后的al集合
	}
	
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	
}

  ArrayList的练习2如下:(难)

/*
需求:将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
比如:存人对象,同姓名同年龄,视为同一个人,为重复元素。
思路:
1、对人描述,将数据封装进人对象。
2、定义容器,将人存入。
3、取出。

List集合判断元素是否相同,依据是元素的equals方法。因为contains方法在比较是否包含的时候,底层原理就是传入元素的equals方法
*/
package pack;

import java.util.*;
class CollectionDemo 
{
	public static void main(String[] args) 
	{	
		ArrayList al = new ArrayList();
		al.add(new Person("lisi01",23));//这往里面存储的是Person类的引用:也就是Person类对象存储的地址值
		al.add(new Person("lisi02",24));//Object obj = new Person("lisi02",24);
		al.add(new Person("lisi03",25));
		al.add(new Person("lisi01",23));
		al.add(new Person("lisi02",24));
		al.add(new Person("lisi04",26));
		
		//首先,我们将Person中的元素取出来看看内容,使用迭代器先取出Person的对象
		Iterator it = al.iterator();
		while(it.hasNext())
		{
			/*
			 直接写:sop(it.next().getName()+"::"+it.next().getAge()); 是不行的!!!
			 1、首先,一次循环中next()2次,指向的不是同一个对象
			 2、对于al.add(new Person("lisi02",24));,add(Object obj),就是说add只能添加Object对象
			 那么在添加对象的时候相当于Object obj = new Person("lisi02",24);,向上类型转换了,
			 因此我们在用it取出的时候取的是Object对象,需要将该对象向下类型转换为Person对象才可以调用Person的获取方法
			 */
			/*
			Object obj = it.next();//先将al中的Person对象取出,放到Person的父类Object的引用obj中(多态)
			//为了使用Person类的特殊方法getName()与getAge(),我们将Object对象obj向下类型转换
			Person p = (Person)obj;
			*/
			//上面2句可以缩写为一句
			Person p = (Person)it.next();
			sop("姓名:"+p.getName()+"  年龄:"+p.getAge());
		}
		
		System.out.println();
		
		//其次我们想要取出重复元素,利用前面的方法!		
//		sop("原集合为:"+al);//直接打印al的对象只会打印出对象的地址值	
		al = singleElement(al);
		Iterator it1 = al.iterator();
		while(it1.hasNext())
		{
			Person p = (Person)it1.next();
			sop("姓名:"+p.getName()+"  年龄:"+p.getAge());
		}
		/*
		 我们用前面获取集合元素的方法打印看看:发现没有去除重复!
		 al这个容器不知道我们判断元素相同的条件!那么他在比较的时候,只判断往里面存储的对象是否相同,
		 那么我们每次添加都会创建新的对象(地址值不同!),那么就算对象的内容是一样的,我们的singleElement方法也会判断其不同!
		 那么我们在Person中重写equals方法,使其比较name与age,那么contains比较的时候(contains底层原理是equals),
		 就会比较equals对象的name与age
		 */
		
		//我们将Person重写的equals方法注释,删除一个内容
		sop("remove 04 :"+al.remove(new Person("lisi04",26)));//remove方法底层也是依赖于元素的equals方法。
		//remove 04 :false。如果我们想删除一个元素,就得判断这个元素再内存中是否存在,而判断是否存在也是equals方法
		//这里new一个新的对象与前面的地址值都不同,Person的equals没有重写比较的是地址值
		
	}
	//去除重复元素的方法
	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))//contains方法会调用Person的equals方法来比较2个对象是否相同(包含)
				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;
	}
	//因为setName()与setAge()使用不到,这里省略,开发必须写
	//外界获取Person类name属性的方法
	public String getName()
	{
		return this.name;
	}
	//外界获取Person类age属性的方法
	public int getAge()
	{
		return this.age;
	}
	
	//我们重写Object的equals方法,Object的equals方法比较的是对象地址,我们比较的是name与age
	//该重写的equals方法是在底层自动被调用的(在contains方法处)!见下面打印出的解释,与视频14-11,13.20分钟的解释
	public boolean equals(Object obj)
	{//注意instanceof是关键字不是方法!不需要加"."引用
		if(!(obj instanceof Person))//如果传入的要比较的类不是Person类,直接返回false
			return false;//这里也可以抛出异常
		Person p = (Person)obj;//先将传入的obj向下转型为Person对象
		
//		System.out.println(this.name+"....."+p.name);
		/*
		 * 打印结果是:
lisi02.....lisi01
lisi03.....lisi01
lisi03.....lisi02
lisi01.....lisi01
lisi02.....lisi01
lisi02.....lisi02
lisi04.....lisi01
lisi04.....lisi02
lisi04.....lisi03
		见视频解释:就是我们在用contains()方法比较Person对象的时候,Person会自动调用自己的equals方法比较前面的对象
		我们重写Object的equals,那么Person的equals方法比较的就是name与age,之前我们没有重写的时候,contains比较的就是对象地址!
		前一个例子我们比较字符串的时候,字符串已经重写了equals,比较的是字符串内容!
		 */
		
		//这里equals与==都是在比较内容是否相同的,int型不能用equals比较(equals只能比较字符串),需要用==比较内容
		//而在String中,equals方法重写用于比较字符串,那么如果本Person对象的name与age等于传入的Person对象的name和age,就返回true
		return this.name.equals(p.name) && this.age == p.age;
	}
}

  注意,ArrayList与LinkedList在比较对象是否相同的时候,底层调用的都是equals方法,因此我们创建的对象如果要存放到ArrayList或LinkedList集合中,必须重写equals方法
参考文章:
java集合详解
java集合中的常用类

6、就业班集合补充
补充1:
  如下:

// 遍历集合
        for (int i = 0; i < list.size(); i++) {
            
        }

这段代码在IDEA中直接“list.fori”回车就出来了
如果你想循环6次,就打“6.fori”回车就可以。
如果你想逆向遍历,使用list.forr+回车即可

如果想获取一个集合的迭代器,如下:
Iterator iterator = list.iterator();
IEAD中的快捷方法是:“list.iterator().var”+回车就可以直接显示

如果想使用增强for循环,IDEA中的快捷键为“list.for

补充2:
  Collection集合接口的特性以及结构如下:注意Collection是所有单列集合的父接口。
黑马毕向东Java课程笔记(day14-1——14-11):集合类(集合框架)——集合类分类与特点+List集合接口及其子类_第3张图片

补充3:
  迭代器泛型的特点

 /*
1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
 注意:
Iterator接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
*/

补充4:
  迭代器实现原理,见就业班-Collection集合-07视频解析
黑马毕向东Java课程笔记(day14-1——14-11):集合类(集合框架)——集合类分类与特点+List集合接口及其子类_第4张图片

补充5:
  增强for循环

/*
    增强for循环:底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写
    是JDK1.5之后出现的新特性
    Collectionextends Iterable:所有的单列集合都可以使用增强for
    public interface Iterable实现这个接口允许对象成为 "foreach" 语句的目标。

    增强for循环:用来遍历集合和数组(既普通数组与Collection集合)

    格式:
        for(集合/数组的数据类型 变量名: 集合名/数组名){
            sout(变量名);
        }
 */

补充6:
  List集合是有序的,有序的意思是元素存储的顺序与取出的顺序是一致的!

List接口特点:

1. 它是一个元素存取有序的集合。例如,存元素的顺序是112233。那么集合中,元素的存储就是按照112233的顺序完成的)。
2. 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
3. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

  测试代码如下:

 //List集合遍历有3种方式
        //使用普通的for循环,使用List的get(int index)来获取角标下的元素
        for(int i=0; i<list.size(); i++){
            //public E get(int index):返回集合中指定位置的元素。
            String s = list.get(i);
            System.out.println(s);
        }
        System.out.println("-----------------");
        //使用迭代器
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }
        System.out.println("-----------------");
        //使用增强for
        for (String s : list) {
            System.out.println(s);
        }

  如前面所说,ArrayList集合的底层数据结构是数组,当ArrayList添加新的元素的时候,就会创建新的数组,因此Arra增删慢。
  LinkedList集合的特点如下

/*
    java.util.LinkedList集合 implements List接口
    LinkedList集合的特点:
        1.底层是一个链表结构:查询慢,增删快
        2.里边包含了大量操作首尾元素的方法
        注意:使用LinkedList集合特有的方法,不能使用多态

        - public void addFirst(E e):将指定元素插入此列表的开头。
        - public void addLast(E e):将指定元素添加到此列表的结尾。
        - public void push(E e):将元素推入此列表所表示的堆栈。

        - public E getFirst():返回此列表的第一个元素。
        - public E getLast():返回此列表的最后一个元素。

        - public E removeFirst():移除并返回此列表的第一个元素。
        - public E removeLast():移除并返回此列表的最后一个元素。
        - public E pop():从此列表所表示的堆栈处弹出一个元素。

        - public boolean isEmpty():如果列表不包含元素,则返回true。

 */

  ArrayList与Vector:Vector是线程安全的集合类,ArrayList并不是线程安全的类(因此ArrayList相对于Vector来说速度较快)。Vector类对集合的元素操作时都加了synchronized,保证线程安全。Vector与ArrayList的扩容并不一样,Vector默认扩容是增长一倍的容量,Arraylist是增长50%的容量。

你可能感兴趣的:(Java资料)