一,集合概述
集合是存储对象最常用的一种方式。关于集合部分的知识点比较零碎,学习后一定要复习。
1,集合类的出现背景:
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储
2,集合与数组的异同
相同点:集合和数组都是一个容器。
不同点:集合长度是可变的,可以存储对象,也只能存储对象;
数组长度是固定的,可以存储对象,也可以存储基本数据类型。
3,集合的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
4,集合结构
因为容器数据结构的不同,出现了容器的体系,经过不断的向上抽取,形成了如下的集合类关系图
二,collection
由上面的图可知,collection是集合类的顶层(根)接口。
Collection接口中定义了集合的共性方法:
1,添加:
boolean add(E); 确保此Collection包含指定的元素
boolean addAll(Collection); 将指定Collection中的所有元素都添加到此Collection中
2,删除
boolean remove(Object); 从此 Collection中移除指定元素的单个实例,如果存在的话
boolean removeAll(Collection); 移除此Collection中那些也包含在指定Collection中的所有元素
void clear();移除此Collection 中的所有元素
3,判断
boolean contains(Object); 如果此 Collection包含指定的元素,则返回 true
Boolean isEmpty();判断容器中是否含有元素,依据size方法
4,获取
Iterator iterator();迭代器
5,获取交集
retainAll(Collection);
a.retainAll(b);将a集合中只保留和b集合共有的元素
6,获取个数
Int size();返回集合中的元素数
7,转成数组
T[] toArray(T[] t);
Collection接口下有两个子接口:List(列表),Set(集)
List:元素是有序的,元素可以重复。因为该集合体系有索引。
Set:元素是无序的,元素不可以重复。
2.1,List
List中特有的一些常用方法
1, 添加:add(index,obj),
2,删除:remove(index)
3,获取:get(index)
4,索引:indexOf(obj)、lastIndexOf(obj)
5,获取字列表:subList(start,end)
6,list集合支持迭代器ListIterator:
Iterator在迭代时,只能对元素进行获取(next())和删除(remove())操作;
ListIterator在迭代list集合时,可添加(add(obj))和修改(set(obj))元素
List组成:
1,ArrayList:底层是数组数据结构,线程不同步,特点:查询速度快,增删稍慢。
2,LinkedList:底层是链表数据结构,线程不同步,特点:查询速度稍慢,增删速度很快。
3,Vector:底层是数组数据结构,线程同步,效率低,在jdk1.2版本后被ArrayList替代。
与其他两个不同,LinkedList有一些自己特有的方法:
1,addFirst();
2, addLast();
3,getFirst();
4,getLast();
5,removeFirst();
6,removeLast();
如果在获取和删除时,容器中没有元素,会抛出异常NoSuchElementException;jdk1.6后,没有元素返回null;
2.2,set
Set集合中没有特有的方法,所有的方法直接继承自Collection。
Set集合组成:HashSet和TreeSet
1, HashSet:底层数据结构是哈希表,线程不同步,存取速度快。判断元素唯一方式:先判断元素的hashCode值是否相同,若相同,再判断元素的equals方法是否为true。
注意:子类LinkedHashSet基于哈希表,又融入了链表,可以对Set集合进行增删提高效率。
示例:
/*
* 在hashSet集合中存入自定义对象,去除重复的元素,并取出元素
* 思路:
* 1,描述手机,对手机的一些属性进行封装
* 2,定义容器,存入手机对象
* 3,使用迭代器取出容器内的对象
* 4,打印结果
*
* */
import java.util.HashSet;
import java.util.Iterator;
public class HashSet1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet<Phone> h = new HashSet<Phone>();
h.add(new Phone("魅族", 5));
h.add(new Phone("苹果", 4));
h.add(new Phone("小米", 3));
h.add(new Phone("华为", 4));
h.add(new Phone("华为", 4));
Iterator<Phone> it = h.iterator();
while(it.hasNext()){
Phone p = (Phone) it.next();
System.out.println(p.getBRAND()+"---"+p.getSIZE());
}
}
}
class Phone{
private String BRAND;
private int SIZE;
public Phone(String brand,int size) {
// TODO Auto-generated constructor stub
this.BRAND = brand;
this.SIZE = size;
}
public String getBRAND() {
return BRAND;
}
public void setBRAND(String bRAND) {
BRAND = bRAND;
}
public int getSIZE() {
return SIZE;
}
public void setSIZE(int sIZE) {
SIZE = sIZE;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(!(obj instanceof Phone)){
return false;
}
Phone p=(Phone)obj;
return this.BRAND.equals(p.BRAND)&&this.SIZE==p.SIZE;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return this.BRAND.hashCode()+this.SIZE;
}
}
1, TreeSet:底层数据结构是二叉树结构。判断元素唯一方式:通过比较方法的return 0来判断元素是否相同。
treeSet可以对Set集合中的元素进行排序,原因是TreeSet类实现了Comparable接口,强制对元素进行比较。
两种排序方式:
1, 让元素自身具有比较性。也就是实现Comparable接口,覆盖compareTo方法,这种方式作为元素的自然排序,也可以说是默认排序。
示例:
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSet1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet<Person1> t = new TreeSet<Person1>();
t.add(new Person1("小明", 21));
t.add(new Person1("小明", 21));
t.add(new Person1("小明", 22));
t.add(new Person1("小红", 21));
t.add(new Person1("小刚", 23));
Iterator<Person1> it = t.iterator();
while(it.hasNext()){
Person1 p = it.next();
System.out.println(p.getName()+"---"+p.getAge());
}
}
}
class Person1 implements Comparable{
private String name;
private int age;
public Person1(String name,int age) {
// TODO Auto-generated constructor stub
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Person1 p = (Person1) o;
if(this.age==p.age)
return this.name.compareTo(p.name);
return this.age-p.age;
}
}
2,自定义比较器。若元素自身不具有比较性,或者元素自身具有的比较性不是自己所需要的,这时只能让容器自身具备。
示例:
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSet2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet<Person2> t = new TreeSet<Person2>(new CompareTest());
t.add(new Person2("小明", 21));
t.add(new Person2("小明", 21));
t.add(new Person2("小明", 22));
t.add(new Person2("小红", 21));
t.add(new Person2("小刚", 23));
Iterator<Person2> it = t.iterator();
while(it.hasNext()){
Person2 p = it.next();
System.out.println(p.getName()+"---"+p.getAge());
}
}
}
class Person2 implements Comparable{
private String name;
private int age;
public Person2(String name,int age) {
// TODO Auto-generated constructor stub
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Person2 p = (Person2) o;
if(this.age==p.age)
return this.name.compareTo(p.name);
return this.age-p.age;
}
}
//定义一个比较器,以姓名长度(name)和年龄(age)比较
class CompareTest implements Comparator<Person2>{
@Override
public int compare(Person2 o1, Person2 o2) {
// TODO Auto-generated method stub
int res=new Integer(o1.getName().length()).compareTo(new Integer(o2.getName().length()));
if (res==0)
{
return new Integer(o1.getAge()).compareTo(o2.getAge());
}
return res;
}
}
那么多容器,如何判断容器的数据结构?
可以通过容器的命名就可以明确其数据结构:
ArrayList:数组Array
LinkedList:链表link
HashSet、HashMap:哈希表hash
TreeSet、TreeMap:二叉树tree
三,迭代器Iterator
迭代器是所有Collection集合共性的取出方式。
1,一般通过两个方法来完成:
hasNext():判断容器中是否有元素
next():取出元素,注意:next方法每调用一次,指针就会放下走。
2,使用方式:
ArrayList a=newArrayList();//创建一个集合
Iterator it=a.iterator();//获取一个迭代器,用于取出集合中的元素。
第一种方式:
for(Iterator iter = a.iterator();iter.hasNext(); )
{
System.out.println(iter.next());
}
第二种方式:
Iterator iter = a.iterator();
while(iter.hasNext())
{
System.out.println(iter.next());
}
1, 使用迭代器注意事项:
迭代器的next方法自动向下取元素,在去之前使用hasNext()判断是否有元素,避免出现NoSuchElementException。
迭代器的next方法返回值类型是Object,所以要记得类型转换。
四,map集合
Map<K,V>集合是一个接口,和List集合及Set集合不同的是,它是双列集合,并且可以给对象加上名字,即键(Key)
特点:一次存入一对元素,以键值对的形式存在,必须保证键的唯一性。
注意:当对象之间存在映射关系时,首先想到的就是使用map集合
4.1 map集合的常用方法
1、添加
put(K key,V value);//添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。
putAll(Map <? extends K,? extends V> m);//添加一个集合
2、删除
clear();//清空
remove(Object key);//删除指定键值对
3、判断
Boolean containsKey(key);//判断键是否存在
Boolean containsValue(value)//判断值是否存在
BooleanisEmpty();//判断是否为空
4、获取
get(key);//通过键获取对应的值
int size();//获取集合的长度
Collection<V>value();//获取Map集合中所以的值,返回一个Collection集合
5,取出:原理是将map集合转成Set集合后,通过迭代器取出。
Set<Map.Entry<K,V>>entrySet();将map集合中的键值映射关系打包成一个Map。Entry对象。
Set<K> keySet();将map集合中所有的键取出存入set集合,再通过get方法获取键对应的值。
注:
HashMap集合可以通过get()方法的返回值来判断一个键是否存在,通过返回null来判断。
HashMap集合可以存入null键null值。
4.2 Map组成结构:
1,HashTable:底层是哈希表数据结构,线程同步,不能存入null键、null值。效率低,被hashMap取代。
2,HashMap:底层是哈希表数据结构,线程不同步,可以存入null键、null值。保证键的唯一性:覆盖hashCode方法和equals方法。
3,TreeMap:底层是二叉树数据结构,可以对map集合中的键进行排序。使用Comparable或Comparator进行比较排序。通过return 0 判断键的唯一性。