黑马程序员05_集合collection

 

集合Collection


 

知识点一:集合概述

  • 引入:

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

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

数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储任意数据类型,集合只能存储对象。

  • 集合类的特点

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

  • Java集合类主要由两个接口派生出来:

Collection

    Set :不能存放重复对象

    List :可存放重复对象,有序

Map

    HashMap 、TreeMap:成对存储

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

  • 集合常用的方法

1、添加:

add(object):添加一个元素

addAll(Collection) :添加一个集合中的所有元素。

2、删除:

clear():将集合中的元素全删除,清空集合。

remove(obj) :删除集合中指定的对象。注意:删除成功,集合的长度会改变。

removeAll(collection) :删除部分元素。部分元素和传入Collection一致。

3、判断:

boolean contains(obj) :集合中是否包含指定元素 。

boolean containsAll(Collection) :集合中是否包含指定的多个元素。

boolean isEmpty():集合中是否有元素。 

4、获取:

int size():集合中有几个元素。

5、取交集:

两个集合元素相同,返回flase;如果retainAll修改了当前集合,返回true。

6、获取集合中所有元素:

Iterator  iterator():迭代器

7、将集合变成数组:

toArray();

PS1add方法的参数类型是Object,以便于接收任意类型对象。

2、集合中存储的都是对象的引用(地址)

 

迭代器

知识点一:概述

Iterator主要遍历Collection集合中的元素,也有称为迭代器或迭代精灵。

知识点二:Iterator的主要方法

boolean hasNext():若被迭代的集合元素还没有被遍历,返回true.

Object  next():返回集合的下一个元素.

void remove():删除集合上一次next()方法返回的元素。(若集合中有多个相同的元素,都可以删掉)

iterator对于集合才能用,for不同,只要是循环都可用。

知识点三:取出容器中元素的方法

  • 方式1

Iterable接口(迭代遍历)  注:优先选择Iterator接口,遍历Collection里所有元素,也称为迭代器和迭代精灵;迭代是取出集合中元素的一种推荐方式。

Iterator it = l.iterator();
while (it.hasNext()) {
System.out.println("迭代输出:" + it.next());
}
  • 方式2:

Foreach循环  注:可以直接用,使用场合:数组和Iterable对象!

for (String str : l) {
System.out.println("for集合迭代输出:" + str);
}
  • 方式3

注:在()内实例化Iterable对象,进行遍历!

int i = 0;// for方法体内定义项不能出现多种不同类型
for (Iterator iter = l.iterator(); i < l.size(); i++) {
System.out.println("for循环迭代实例化输出:" + iter.next());
  • 方式4

先用toArray方法输出成为数组,再用Foreach循环!

Object[] o = l.toArray();
for (Object object : o) {
System.out.println("转换数组迭代输出:" + object);
}

第一个和第三个很类似,第二个和第四个很类似!

 

Collection的子集:

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

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

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

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

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

 

 

List

List

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

知识点一:List常用的方法

add(index,element);     / /在指定位置添加元素,如:al.add(1,"java09");

addAll(index,Collection);

remove(index);         //删除指定位置,如:al.remove(2);

set(index,element);     //修改元素,如:al.set(2,"java007");

get(index):            //通过角标获取元素。如:get(1)

subList(from,to);   如: sub = al.subList(1,3),含第1个不含第3

int indexOf(obj):    获取指定元素的位置。如:indexOf("java02")

知识点二:

List集合特有的迭代器:ListIterator,特有包括remove,add,set等(因为含有角标)

从集合里取出元素有两种方法,一种通过迭代器,一种通过容器。但是两者同时使用就会出现错误,如下:

  List li = al.list();
		while(li.hasNext())
		{
			Object obj = li.next();    //迭代器的方法
			if(obj.equals("java02"))   
				a1.add("java009");  //容器的添加方法
		}

必须使用两种相同的方法进行操作,代码如下:

  List li = al.List();
			while(li.hasNext())
		{
			Object obj = li.next();
			if(obj.equals("java02"))
				li.remove("java002");
		}

  

可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。代码如下:

	ListIterator li = al.listIterator();
		while(li.hasNext())
		{
			Object obj = li.next();
			if(obj.equals("java02"))
				li.add("java009");
				li.set("java006");
		}

  

 

ArrayList

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

原始长度为10

练习1

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

实现思想:创建一个新的容器,将要去除重复元素的容器中的每一个元素放进新的容器中,放的同时比较是否与已有元素相同,只有不相同的才放。

主要的方法的代码:

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;
	}
}

/*练习2

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

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

思路:

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

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

3、利用上题中singleElement方法去除相同元素。

List集合判断元素是否相同,依据是元素的equals方法。

*/

 

  • 知识点1

al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30);
Iterator it = al.iterator();
		while(it.hasNext())
		{
			Person p = (Person)it.next();  
         //传进的是Object的子类Person,需要强制转换成Person才能访问Person的方法
			sop(p.getName()+"::"+p.getAge());
		}

  

  • 知识点2利用singleElement方法去除相同元素

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;
	}
}

  

 

知识点3singleElement方法中的contains方法调用的是equals,但是系统自定义的equals方法不识别相同的人。只能重写Person类中的equals方法。

代码如下:

public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))  //首先判断传进去的类是否属于Person类
			return false;
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}

  

 

LinkedList

底层使用的链表数据结构。

特点:增删速度很快,查询稍慢。线程不同步。

LinkedList:特有方法:

addFirst();  

addLast();  

getFirst();  

getLast();  

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

removeFirst();

removeLast();

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

不用迭代器去除LinkedList中的元素:

while(!link.isEmpty())

{

sop(link.removeLast());

}

JDK1.6出现了替代方法。

offerFirst();

offerLast();

peekFirst();

peekLast();

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

pollFirst();

pollLast();

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

 

/*练习1

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

堆栈:先进后出  如同一个杯子。

队列:先进先出 First in First out  FIFO 如同一个水管。

思想:自己定义一个容器,利用已有容器中的方法,来实现特殊的需要。

import java.util.*;
class DuiLie
{
	private LinkedList link;
	DuiLie()
	{
		link = new LinkedList();
	}
	
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
	public Object myGet()
	{
		return link.removeLast();
	}
	public boolean isNull()
	{
		return link.isEmpty();
	}

}

class  LinkedListTest
{
	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());
		}
	}
}

  

 

 


 

Vector

枚举就是Vector特有的取出方式。枚举和迭代器很像。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。枚举郁郁而终了。

知识点1:遍历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();
		while(en.hasMoreElements())
		{
			System.out.println(en.nextElement());
		}
	}
}

  

 


 

Set

Set体系

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

  |--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。

  HashSet是如何保证元素唯一性的呢?

  是通过元素的两个方法,hashCodeequals来完成。

  如果元素的HashCode值相同,才会判断equals是否为true

  如果元素的hashcode值不同,不会调用equals

  注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcodeequals方法。

  |--TreeSet

HashSet

知识点一:hashSet中的add()方法返回的是Boolean,如果元素不重复添加成功则返回true,否则返回false

知识点二:系统中的hashCode方法自动算出传入HashSet中元素的哈希值,然后根据哈希值存储元素。也可以通过重写HashCode方法,自己设计哈希值。代码如下:

Public int hashCode()

{

return 50;

}

知识点三:hashSet保证元素唯一,是通过元素的两个方法,hashCodeequals来完成。首先比较两个元素的哈希值,如果不同,则添加,如果哈希值相同再继续调用equeals方法比较内容,内容相同则重复,否则,就添加

知识点四:如果元素的HashCode值相同,才会继续判断equals是否为true。如果元素的hashcode值不同,不会调用equals

 

TreeSet

|--TreeSet可以对Set集合中的元素进行排序。

底层数据结构是二叉树。

保证元素唯一性的依据:

compareTo方法return 0.

  • TreeSet排序的第一种方式:

让元素自身具备比较性。

元素需要实现Comparable接口,覆盖compareTo方法。

这种方式也成为元素的自然顺序,或者叫做默认顺序。

  • TreeSet的第二种排序方式:

当元素自身不具备比较性时,或者具备的比较性不是所需要的。

这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。

注意:当两种排序都存在时,以比较器为主。

知识点一:可以对Set集合中的元素进行排序。按自然顺序排序

如:

TreeSet ts = new TreeSet();
        ts.add(“a”);
        ts.add(“c”);
        ts.add(“b”);
        ts.add(“d”);

使用迭代器输出顺序为:abcd

知识点二:TreeSet元素的自定义排序

TreeSet排序的第一种方式:让元素自身具备比较性。这时需要实现Comparable接口,覆盖compareTo方法。排序时,当主要条件相同时,一定判断一下次要条件。

代码如下:

class Student implements Comparable
{
	private String name;
	private int age;
	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj)
	{
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;

		if(this.age>s.age)      //从小到大排序
			return 1;
		if(this.age==s.age) 
		{
			return this.name.compareTo(s.name);  // 当主要的条件相同时,比较次要条件
		}
		return -1;
	}

PS1TreeSet的底层数据结构为二叉树,左大右小。

2compareTo方法直接返回1时,用迭代器去元素时将按照存放的顺去取出。

如:

  public int compareTo
  	{
			return 1;
		}

  

知识点三:TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

如:

class MyCompare implements Comparator
{
	public int compare(Object o1,Object o2)
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
		{

			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
  //把年龄封装成对象用compareTo方法实现比较,返回int,写起来更简单
			/*
			if(s1.getAge()>s2.getAge())
				return 1;
			if(s1.getAge()==s2.getAge())
				return 0;
			return -1; 
			*/
		
		return num;
	}
}

  

构造TreeSet对象时,代码如下:

TreeSet ts = new TreeSet(new MyCompare());

 

TreeSet练习1:

/*

需求:按照字符串长度排序。

思想:字符串本身具备比较性。但是它的比较方式不是所需要的。这时就只能使用比较器。

*/

 

		TreeSet ts = new TreeSet(new StrLenComparator());//构造TreeSet
	
class StrLenComparator implements Comparator
{
	public int compare(Object o1,Object o2)
	{
		String s1 = (String)o1;
		String s2 = (String)o2;
  int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
  		if(num==0)   //当长度相同时,按照次要条件排序
  		return s1.compareTo(s2);
  		return num;
	}

  

 

posted @ 2014-03-10 13:31  让痛苦变成美好的回忆  阅读(139)  评论(0编辑  收藏  举报