黑马程序员——集合框架之Collection

时间:2023-02-18 20:38:26
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一、集合以及集合框架的顶层接口Collection接口

集合类的由来:对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。就使用集合容器进行存储。
集合特点:1、用于存储对象的容器;2、集合的长度是可变的;3、集合中不可以存储基本数据类型值。 
集合框架:集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。

集合框架的顶层Collection接口:
Collection
|--List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
|--Set:元素不能重复,无序。

Collection的常见方法:

1、添加。
向集合中添加元素:boolean add(Object obj);
将某个集合的所有元素添加到本集合中:boolean addAll(Collection coll);
2、删除。
删除集合中的某个元素:boolean remove(object obj);
将集合中的元素全部删除:boolean removeAll(Collection coll);
清空集合:void clear();
3、判断:
判断集合是否包含某个元素:boolean contains(object obj);
判断集合是否包含另一个集合:boolean containsAll(Colllection coll);
判断集合中是否有元素:boolean isEmpty();
4、获取:
获取集合的长度:int size();
Iterator iterator():取出元素的方式:使用迭代器。
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。所以该迭代器对象是在容器中进行内部实现的。对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,也就是iterator方法。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
//代码示例
public class IteratorDemo {

public static void main(String[] args) {

Collection coll = new ArrayList();

//使用了Collection中的iterator()方法。 调用集合中的迭代器方法,是为了获取集合中的迭代器对象。
Iterator it = coll.iterator();
while(it.hasNext()){
System.out.println(it.next());
}

for(Iterator it = coll.iterator(); it.hasNext(); ){
System.out.println(it.next());
}
}
}
5、其他:
取两个集合的交集:boolean retainAll(Collection coll);
将集合转成数组:Object[] toArray();

二、List List:特有的常见方法:有一个共性特点就是都可以操作角标。list集合是可以完成对元素的增删改查。
添加:void add(index,element);void add(index,collection);
删除;Object remove(index);
修改:Object set(index,element);
获取:Object get(index);int indexOf(object);int lastIndexOf(object);List subList(from,to);

List:
|--Vector:内部是数组数据结构,是同步的。增删,查询都很慢! |--ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。 |--LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。

1、vector特有的取出方式
/*
枚举就是Vector特有的取出方式。
发现枚举和迭代器很像,其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。
*/
public 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());
}
}
}

2、LinkedList
LinkedList的特有方法:
在链表头部添加元素:addFirst();在链表尾部添加元素:addLast();

获取链表中的第一个元素:getFirst();获取链表中的最后一个元素:getLast();
获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException。

删除链表中的第一个元素:removeFirst();删除链表中的第一个元素:removeLast();
获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException。

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

在链表头部添加元素:offerFirst();在链表尾部添加元素:offerLast();

获取链表中的第一个元素:peekFirst();获取链表中的最后一个元素:peekLast();
获取元素,但不删除元素。如果集合中没有元素,会返回null。

删除链表中的第一个元素:pollFirst();删除链表中的第一个元素:pollLast();
获取元素,但是元素被删除。如果集合中没有元素,会返回null。

3、ArrayList练习:将自定义对象作为元素存到ArrayList集合中,并去除重复元素。 比如:存人对象。同姓名同年龄,视为同一个人。为重复元素。
思路:1,对人描述,将数据封装进人对象。2,定义容器,将人存入。3,取出。
public class Person{
private String name;
private int age;
Person(String name,int age){
this.name = name;
this.age = age;
}

public boolean equals(Object obj){

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

public String getName(){
return name;
}
public int getAge(){
return age;
}
}
public class ArrayListTest2 {public static void sop(Object obj){System.out.println(obj);}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("lisi04",35));al.add(new Person("lisi03",33));//al.add(new Person("lisi04",35));//al = singleElement(al);sop("remove 03 :"+al.remove(new Person("lisi03",33)));//remove方法底层也是依赖于元素的equals方法。Iterator it = al.iterator();while(it.hasNext()){Person p = (Person)it.next();sop(p.getName()+"::"+p.getAge());}}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;}}

三、Set
Set:元素不可以重复,是无序。Set接口中的方法和Collection一致。
|--HashSet: 内部数据结构是哈希表 ,是不同步的。
如何保证该集合的元素唯一性呢?
是通过对象的hashCode和equals方法来完成对象唯一性的。
如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。 
如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。
建立对象判断是否相同的依据。
|--TreeSet:可以对Set集合中的元素进行排序。是不同步的。 
判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。 

TreeSet对元素进行排序的方式一:
让元素自身具备比较功能,需要实现Comparable接口。覆盖compareTo方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。

哈希表确定元素是否相同
if(this.hashCode()== obj.hashCode() && this.equals(obj))
1),判断的是两个元素的哈希值是否相同。如果相同,在判断两个对象的内容是否相同。
2),判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。
注意:如果哈希值不同,是不需要判断equals。


1、hashSet练习:往hashSet集合中存储Person对象。如果姓名和年龄相同,视为同一个人。视为相同元素。
public class Person{

private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public int hashCode() {
//System.out.println(this+".......hashCode");
return name.hashCode()+age*27;
//return 100;
}
@Override
public boolean equals(Object obj) {

if(this == obj)
return true;
if(!(obj instanceof Person))
throw new ClassCastException("类型错误");
//System.out.println(this+"....equals....."+obj);
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return name+":"+age;
}
}
public class HashSetTest {public static void main(String[] args) {HashSet hs = new HashSet();/* * HashSet集合数据结构是哈希表,所以存储元素的时候, * 使用的元素的hashCode方法来确定位置,如果位置相同,在通过元素的equals来确定是否相同。 */hs.add(new Person("lisi4",24));hs.add(new Person("lisi7",27));hs.add(new Person("lisi1",21));hs.add(new Person("lisi9",29));hs.add(new Person("lisi7",27));Iterator it = hs.iterator();while(it.hasNext()){Person p = (Person)it.next();System.out.println(p);}}}

2、往treeSet集合中存储Person对象。以Person对象年龄进行从小到大的排序。
方式1:是元素具备比较性,即使Person对象具备比较性,复写CompareTo方法
public class Person implements Comparable {

private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public int hashCode() {
return name.hashCode()+age*27;
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(!(obj instanceof Person))
throw new ClassCastException("类型错误");
return this.name.equals(p.name) && this.age == p.age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return name+":"+age;
}
@Override
public int compareTo(Object o) {
Person p = (Person)o;
int temp = this.age-p.age;
return temp==0?this.name.compareTo(p.name):temp;
}

}
public class TreeSetDemo {public static void main(String[] args) {TreeSet ts = new TreeSet();//以Person对象年龄进行从小到大的排序。ts.add(new Person("zhangsan",28));ts.add(new Person("lisi",21));ts.add(new Person("zhouqi",29));ts.add(new Person("zhaoliu",25));ts.add(new Person("wangu",24));Iterator it = ts.iterator();while(it.hasNext()){Person p = (Person)it.next();System.out.println(p.getName()+":"+p.getAge());}}}
方式2:使容器具备比较性,定义一个类,实现Comparator接口,覆盖compare方法
/**
* 创建了一个根据Person类的name进行排序的比较器。
*/
public class ComparatorByName implements Comparator {

@Override
public int compare(Object o1, Object o2) {

Person p1 = (Person)o1;
Person p2 = (Person)o2;

int temp = p1.getName().compareTo(p2.getName());

return temp==0?p1.getAge()-p2.getAge(): temp;
//return 1;//有序。
}
}

3、treeSet:练习对字符串进行长度排序。
public class ComparatorByLength implements Comparator {
@Override
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;
int temp = s1.length()-s2.length();
return temp==0? s1.compareTo(s2): temp;
}
}
public static void main(String[] args) {TreeSet ts = new TreeSet(new ComparatorByLength());ts.add("aaaaa");ts.add("zz");ts.add("nbaq");ts.add("cba");ts.add("abc");Iterator it = ts.iterator();while(it.hasNext()){System.out.println(it.next());}}}