黑马程序员——Java基础——集合(一)

来源:互联网 发布:网络作家的生活 编辑:程序博客网 时间:2024/06/16 03:57

------<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;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int hashCode() {return name.hashCode()+age*27;}@Overridepublic boolean equals(Object obj) {//同一个对象存两次,直接返回trueif (this == obj)return true;//对象为空返回falseif (obj == null)return false;//存储的对象不是所需类的抛出ClassCastExceptionif (!(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;}@Overridepublic 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方法,先按照姓名排序,姓名相同按年龄排@Overridepublic 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;}@Overridepublic 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{@Overridepublic 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);}}}







0 0