------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一、集合
为了方便多个对象的操作,我们需要把多个对象存储到一个容器中,数组除了存储基本数据类型也可以存储对象,但数组的长度是固定的,所以抽取了一个长度可变,只能存储对象且不同类型对象的容器,就是集合。对于集合容器,有很多种。因为每一个容器的自身特点不同,其实原理在于每个容器的内部数据结构不同。集合容器在不断向上抽取过程中就出现了集合体系,Collection就是集合体系的根接口,集合框架的构成及分类:
Collection接口中定义了集合框架的共性功能。
1.添加
boolean add(Object obj);
boolean addAll(Collection coll);
2.删除
boolean remove(Object obj);
boolean removeAll(Collection coll);
boolean isEmpty();判断集合中是否有元素
3.判断
boolean contains(Object obj);
boolean containsAll(Collection coll);
boolean isEmpty();判断集合中是否有元素。
4.获取
int size();
Iterator iterator();
取出元素的方式:迭代器,该对象必须依赖于具体容器,因为每一个容器的数据结构都不同,所以该迭代器对象是在容器中进行内部实现的,也就是iterator方法在每个容器中的实现方式是不同的。使用时只要通过容器获取到该实现的迭代器的对象即可,也就是iterator方法。
JDK1.5提供了高级for循环获取集合元素,但是不能对集合进行操作。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
5.获取交集
boolean retainAll(Collection coll);取交集
6.集合变数组
Object toArray();
因为Collection是抽取出来的一个接口,所以想要使用共性方法必须建立子类对象。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建集合
Collection col = new ArrayList();
//添加元素
col.add("java01");
col.add("java02");
col.add("java03");
col.add("java04");
//用迭代器获取集合中的元素
Iterator it = col.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
System.out.println("---------------");
//删除元素
col.remove("java02");
//使用高级for循环获取集合中的元素
for(Object obj : col)
{
System.out.println(obj);
}
//获取集合中的元素个数
System.out.println("集合中的元素个数:"+col.size());
//判断集合中是否包含指定元素
System.out.println("集合中有没有java02的元素:"+col.contains("java02"));
}
}
Collection
|--List:存取的元素有序(存入和取出的顺序一致),元素都有索引(角标),允许重复元素
|--Set:元素不能重复,无序
二、List
List是Collection接口的子接口,所以除了Collection接口的共性方法,还有自己的特有方法。因为有索引所以特有方法可以操作角标。
List:
|--Vector:底层是数组数据结构,是同步的。增删,查询都很慢。
|--ArrayList:底层是数组数据结构,是不同步的,替代了Vector。替代了Vector,查询的速度快。
|--LinkedList:底层是链表数据结构,是不同步的。增删元素的速度很快。
List集合的特有方法:
1.添加
void add(index,element);在指定的索引位插入元素。
void addAll(index,collection);在指定的索引位插入一个集合的所有元素
2.删除
Object remove(index);删除指定索引位的元素,返回被删的元素。
3.修改
Object set(index,element);对指定索引位进行元素的修改。
4.获取:
Object get(index);通过索引获取指定元素。
int indexOf(object);获取指定元素第一次出现的索引位,如果该元素不存在返回-1;所以,通过-1,可以判断一个元素是否存在
int lastIndexOf(object);反向索引指定元素的位置。
List subList(from,to);获取子列表。
5.获取所有元素
ListIterator listIterator();List集合特有的迭代器,ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以在迭代器时,只能用迭代器的方法操作元素。可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作,如添加、修改等,就需要使用其子接口ListIterrator。该接口只能通过List集合的ListIterator方法获取。
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListDemo {
public static void main(String[] args) {
//创建List集合对象
List lists = new ArrayList();
//添加元素
lists.add("java01");
lists.add("java02");
lists.add("java03");
lists.add("java04");
//使用迭代器子接口ListIterator获取集合元素
ListIterator it = lists.listIterator();
while(it.hasNext())
{
System.out.println(it.next());
}
System.out.println("--------------");
//在指定索引添加元素
lists.add(2, "java05");
//删除指定索引的元素并获取
System.out.println("删除元素:"+lists.remove(3));
//修改指定索引的元素
System.out.println("修改元素:"+lists.set(0, "java000"));
//获取指定索引的元素
System.out.println("java04所在的索引是:"+lists.indexOf("java04"));
//通过索引获取集合元素
for(int x = 0 ; x < lists.size() ; x++)
{
System.out.println(lists.get(x));
}
//获取子列表
System.out.println("子列表:"+lists.subList(0, 2));
}
}
其中,LinkedList作为List的子类,也有其自身的特有方法
1.添加元素
void addFirst(element);将指定元素插入此列表的开头。
void addLast(element);将指定元素添加到此列表的结尾。
2.获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException
getFirst();返回此列表的第一个元素。
getLast();返回此列表的最后一个元素。
3.删除元素,同时获取元素。如果集合中没有元素,会出现NoSuchElementException
removeFirst();移除并返回此列表的第一个元素。
removeLast();移除并返回此列表的最后一个元素。
在JDK1.6出现了替代方法。
1.插入元素
boolean offerFirst();在此列表的开头插入指定的元素。
boolean offerLast(); 在此列表末尾插入指定的元素。
2.获取元素
peekFirst(); 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
peekLast();获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
3.删除元素
pollFirst();获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
pollLast();获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
//创建LinkedList集合对象
LinkedList list1 = new LinkedList();
//将指定元素插入开头
list1.addFirst("java01");
list1.addFirst("java02");
//将指定元素插入结尾
list1.addLast("java03");
list1.addLast("java04");
//获取列表第一个元素
System.out.println("列表第一个元素:"+list1.getFirst());
//获取列表最后一个元素
System.out.println("列表最后一个元素:"+list1.getLast());
System.out.println(list1);
//获取并删除列表第一个元素
System.out.println("要删除的第一个元素:"+list1.removeFirst());
//获取列表最后一个元素
System.out.println("要删除的最后一个元素:"+list1.removeLast());
System.out.println(list1);
System.out.println("---------------");
//JDK1.6替代方法
//创建LinkedList集合对象
LinkedList list2 = new LinkedList();
//将指定元素插入开头
list2.offerFirst("java01");
list2.offerFirst("java02");
//将指定元素插入结尾
list2.offerLast("java03");
list2.offerLast("java04");
//获取列表第一个元素
System.out.println("列表第一个元素:"+list2.peekFirst());
//获取列表最后一个元素
System.out.println("列表最后一个元素:"+list2.peekLast());
System.out.println(list2);
//获取并删除列表第一个元素
System.out.println("要删除的第一个元素:"+list2.pollFirst());
//获取列表最后一个元素
System.out.println("要删除的最后一个元素:"+list2.pollLast());
System.out.println(list2);
}
}
三、Set
Set:无序,不可以重复元素。Set接口中的方法和Collection一致。
1.HashSet:底层数据结构是哈希表,线程不同步。
保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。如果为true,那么视为相同元素,不存。如果为false,那么存储。如果元素的hashCode值不同,不会调用equals。
哈希表的原理:
对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值称为哈希值,哈希值就是这个元素的位置。如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础+1顺延。存储哈希值的结构,我们称为哈希表。既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。
//创建Person类,定义name和age属性,创建set、get方法,复写toString方法方便打印
//姓名和年龄相同视为相同元素,复写hashCode和equals方法
class Person
{
private String name ;
private int 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 Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
return name.hashCode()+age*27;
}
@Override
public boolean equals(Object obj) {
//同一个对象存两次,直接返回true
if (this == obj)
return true;
//对象为空返回false
if (obj == null)
return false;
//存储的对象不是所需类的抛出ClassCastException
if (!(obj instanceof Person))
throw new ClassCastException("类型错误");
Person p = (Person) obj;
return this.name.equals(p.name)&&this.age == p.age;
}
}
//往HashSet集合中存储Person对象。如果姓名和年龄相同,视为同一个人,视为相同元素。
public class HashSetDemo {
public static void main(String[] args) {
//添加不同的的对象进行验证
HashSet hs = new HashSet();
hs.add(new Person("zhangsan01",10));
hs.add(new Person("zhangsan02",10));
hs.add(new Person("zhangsan03",10));
hs.add(new Person("zhangsan01",13));
hs.add(new Person("zhangsan01",10));
for(Iterator it = hs.iterator();it.hasNext();)
{
System.out.println(it.next());
}
}
}
2.TreeSet:可以对Set集合中的元素进行排序,底层数据结构是二叉树。
保证元素唯一性的依据:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。在判断时,需要分主要条件和次要条件,当主要条件相同时,再判断次要条件,按照次要条件排序。
TreeSet对元素进行排序的方式一:让元素自身具备比较功能,元素就需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。
//实现Comparable接口,复写compareTo方法,让Person元素自带比较性
class Person implements Comparable{
private String name;
private int 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 Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
//复写hashCode和equals方法方便其他调用
public int hashCode() {
return name.hashCode() + age * 27;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Person))
throw new ClassCastException("类型错误");
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
}
//复写compareTo方法,先按照姓名排序,姓名相同按年龄排
@Override
public int compareTo(Object o) {
if (!(o instanceof Person))
throw new ClassCastException("类型错误");
Person p = (Person) o;
int num = this.getName().compareTo(p.getName());
return num == 0 ? this.getAge() - p.getAge(): num ;
}
}
//往TreeSet集合中存储Person对象,验证排序
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Person("zhangsan01",10));
ts.add(new Person("zhangsan03",10));
ts.add(new Person("zhangsan02",10));
ts.add(new Person("zhangsan01",13));
ts.add(new Person("zhangsan02",10));
for(Object obj : ts)
{
Person p = (Person) obj ;
System.out.println(p);
}
}
}
如果不要按照对象中具备的自然顺序进行排序,就使用TreeSet集合第二种排序方式:让集合自身具备比较功能,定义一个类实现Comparator接口,复写compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
import java.util.Comparator;
import java.util.TreeSet;
class Person {
private String name;
private int 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 Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
//复写hashCode和equals方法方便其他调用
public int hashCode() {
return name.hashCode() + age * 27;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Person))
throw new ClassCastException("类型错误");
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
}
}
//自定义一个比较器,复写compare方法,先按年龄排序,后按姓名排序
class PersonComparator implements Comparator
{
@Override
public int compare(Object o1, Object o2) {
if (!(o1 instanceof Person))
throw new ClassCastException("类型错误");
if (!(o2 instanceof Person))
throw new ClassCastException("类型错误");
Person p1 = (Person) o1;
Person p2 = (Person) o2;
int num = p1.getAge()-p2.getAge();
return num == 0 ? p1.getName().compareTo(p2.getName()) : num ;
}
}
//定义TreeSet集合,传入自定义的比较器对象,验证排序
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new PersonComparator());
ts.add(new Person("zhangsan01",10));
ts.add(new Person("zhangsan03",10));
ts.add(new Person("zhangsan02",10));
ts.add(new Person("zhangsan01",13));
ts.add(new Person("zhangsan02",10));
for(Object obj : ts)
{
Person p = (Person) obj ;
System.out.println(p);
}
}
}