一、 集合类概述
1.1、为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
1.2、数组和集合类同是容器,有什么不同呢?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型;集合只能存储对象。
集合框架出现许多容器的原因:因为每一个容器对数据的存储方式不同,这个存储方式称之为:数据结构。
1.3、集合的特点
集合只用于存储对象;集合长度是可变的;集合可以存储不同类型的对象。
二、 List
List:元素是有序的,元素可以重复,因为该集合体系有索引;
List集合判断元素是否相同,依据的是元素的equals方法。
List特有方法:
A、增
void add(int index,element):在指定角标插入指定元素;
boolean add(E e):向集合中添加元素;
boolean addAll(int index, Connection e):在指定位置插入指定的集合e;
B、删
E remove(int index):移除列表中指定位置的元素;
boolean remove(Object o):从此列表中移除第一次出现的指定元素(如果存在)(可选操作);
boolean removeAll(Collection<?> c):从列表中移除指定 collection 中包含的其所有元素(可选操作);
C、改
E set(int index,element):用指定元素替换列表中指定位置的元素;
D、 查
E get(int index):获取指定角标的元素;
Lise subList(int fromIndex,int toIndex):获取从fromIndex(包括 )和 toIndex(不包括)之间的子集合;
示例:
- import java.util.*;
- class ListDemo
- {
- public static void main(String[] args)
- {
- ArrayList al = new ArrayList();
- al.add("day01");
- al.add("day02");
- al.add("day03");
- al.add("day04");
- ArrayList al1 = new ArrayList();
- al1.add("day11");
- al1.add("day12");
- //al.add(2,"day08"); //在第二个位置上增加一个元素"day08";
- //System.out.println(al); //打印结果:[day01, day02, day08, day03, day04];
- //al.addAll(al1); //将al1集合中所有的元素添加到al集合中;
- //System.out.println(al); //打印结果:[day01, day02, day03, day04, day11, day12];
- //al.remove(2); //将集合中位置2上的元素删除;
- //System.out.println(al);//打印结果:[day01, day02, day04];
- //al.set(2,"day08"); //将集合中位置2上的元素更改为day08;
- //System.out.println(al);//打印结果:[day01, day02, day08, day04];
- //System.out.println(al.get(2));// 获取位置2上的元素;
- for(Iterator it = al.iterator(); it.hasNext(); )
- {
- System.out.println(it.next());
- }
- //获取元素位置;
- System.out.println(al.indexOf("day02"));
- //从指定位置获取一个新的子集合。
- List sub = al.subList(1,3);
- System.out.println(sub);
- }
- }
2.1、ListIterator
ListIterator:List集合特有的迭代器。是Iterator的子接口。ListIterator可以在遍历元素的时候对元素进行增删改查等操作。
在迭代时不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常,所以在迭代时只能用迭代器操作方法操作元素,但是Iterator的方法有限,只能对元素进行判断、取出、删除的操作,如果想要其他操作如添加、修改等,就需要使用其子接口ListIterator,该接口只能通过List集合的Listiterator方法获取。
示例:
- import java.util.*;
- class ListDemo1
- {
- public static void main(String[] args)
- {
- ArrayList al = new ArrayList();
- al.add("day01");
- al.add("day02");
- al.add("day03");
- al.add("day04");
- System.out.println(al);
- for(ListIterator li = al.listIterator();li.hasNext(); )
- { //此时如果用Iterator it = al.iterator(),
- //将会发生ConcurrentModificationException异常;
- Object obj = li.next();
- if(obj.equals("day02"))
- //li.add("java");//在day02后添加元素java;
- li.set("java"); //将day02更改为java;
- }
- System.out.println(al);
- }
- }
List常用的三个子类:ArrayList,LinkedList、Vector
各自特点(重点):
ArrayList:底层使用的数据结构是数组结构。查询速度很快,但增删稍慢,线程不同步。
LinkedList:底层使用的数据结构是链表数据结构。增删很快,但查询较慢。
Vector:底层使用的是数组数据结构。线程同步,现已被ArrayList替代。
Enumeration(枚举):枚举是Vector特有的取出元素的方式,枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长,所以枚举被迭代器替代了。
2.2、ArrayList子类共性方法
1)、add方法中的参数类型是Object,以便于接受任意类型对象;
2)、集合中存储的都是对象的引用(地址)。
常用方法:
1)、int size(); //获取集合长度
2)、boolean remove(Object o) //删除集合中某个对象;
3)、boolean removeAll(Cllection c) //删除集合同的对象;
4)、boolean retainAll(Collection c)//保留集合中相同的对象;
5)、Iterator itorator();
迭代器:取出集合中元素的方式。
示例:
- import java.util.*;
- class CollectionDemo
- {
- public static void main(String[] args)
- {
- method2();
- }
- public static void method2()
- {
- ArrayList al = new ArrayList();
- al.add("day01");
- al.add("day02");
- al.add("day03");
- al.add("day04");
- for(Iterator it = al.iterator(); it.hasNext(); )
- { //获取迭代器用于取出集合中的元素;
- System.out.println(it.next());
- }
- }
- public static void method()
- {
- ArrayList al = new ArrayList();
- al.add("day01");
- al.add("day02");
- al.add("day03");
- al.add("day04");
- //al.clear();
- al.remove("day01"); //删除集合中的对象;
- System.out.println("集合是否为空:"+al.isEmpty());//判断集合是否为空;
- System.out.println("集合对象:"+al); //打印集合中的对象;
- System.out.println("集合中包含day01:"+al.contains("day01"));//集合中是否包含某一对象;
- System.out.println("al长度:"+al.size());//打印集合长度
- }
- public static void method1()
- {
- ArrayList al1 = new ArrayList();
- al1.add("day01");
- al1.add("day02");
- al1.add("day03");
- al1.add("day04");
- ArrayList al2 = new ArrayList();
- al2.add("day01");
- al2.add("day02");
- al2.add("day06");
- al2.add("day07");
- al1.removeAll(al2);//删除集合中相同的对象;
- //al1.retainAll(al2); //保留集合中相同的对象;
- System.out.println(al1);
- System.out.println(al2);
- }
- }
2.3、LinkedList类共性方法
LinkedList特有方法:
addFirst();
addLast();
getFirst(); 可以获取元素,但不删除元素;如果集合中没有元素,将会
getLast(); 抛出noSuchElementException异常
removeFirst(); 可以获取元素,同时删除元素;如果集合中没有元素,将
removeLast(); 会抛出noSuchElementException异常
在JDK1.6版本后出现了替代方法:
pollFirst(); 可以获取元素,但会删除元素;如果集合中没有元素,将会
pollLast(); 返回null。
offerFirst(); 在集合开头插入一个元素;
offerLast(); 在集合结尾插入一个元素;
peekFirst(); 可以获取元素,同时不删除元素;如果集合中没有元素,将
peekLast(); 返回null。
示例:
- import java.util.*;
- class LinkedListDemo
- {
- public static void main(String[] args)
- {
- LinkedList link = new LinkedList();
- link.add("day01");
- link.add("day02");
- link.add("day03");
- link.add("day04");
- //获取第一个元素;打印结果:day01;
- //System.out.println(link.getFirst());
- //删除第一个元素;打印结果:day01;
- //但集合中的第一个元素被删除;
- //System.out.println(link.removeFirst("day08"));
- System.out.println(link.offerFirst("day08"));
- System.out.println(link);
- //获取集合中所有元素;
- while(!link.isEmpty())
- {
- //顺着打印
- //System.out.println(link.removeFirst());
- //倒着打印
- System.out.println(link.removeLast());
- }
- }
- }
练习:
1、向一个集合中存入对象,同时又从中取出对象,要求先进的先出,后进的后出。
- 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("day01");
- dl.myAdd("day02");
- dl.myAdd("day03");
- dl.myAdd("day04");
- while(!dl.isNull())
- {
- System.out.println(dl.myGet());
- }
- }
- }
2、删除集合中重复的元素。
- import java.util.*;
- class ArrayListTest
- {
- public static void main(String[] args)
- {
- ArrayList al = new ArrayList();
- al.add("day01");
- al.add("day08");
- al.add("day05");
- al.add("day01");
- al.add("day07");
- al = singleElement(al);
- System.out.println(al);
- }
- public static ArrayList singleElement(ArrayList al)
- {
- ArrayList newal = new ArrayList();
- Iterator it = al.iterator();
- while(it.hasNext()) //使用迭代器遍历集合al中的元素;
- {
- Object obj = it.next();
- if(!newal.contains(obj))//将集合中已有的元素去掉;
- newal.add(obj); //将al中的元素添加到newal中(不包含重复元素);
- }
- return newal;
- }
- }
3、将自定义对象作为元素存入到集合里,并去除重复元素。
- import java.util.*;
- 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;
- return this.name.equals(p.name) && this.age == p.age;
- }
- public String getName()
- {
- return name;
- }
- public int getAge()
- {
- return age;
- }
- }
- class ArrayListTest1
- {
- public static void main(String[] args)
- {
- ArrayList al = new ArrayList();
- al.add(new Person("lisi01",12));//al.add(Object o);
- al.add(new Person("lisi02",8));
- al.add(new Person("lisi02",8));//Object obj = new Person("lisi01",12);类型被提升为Object;
- al.add(new Person("lisi03",32));
- al.add(new Person("lisi04",28));
- al.add(new Person("lisi04",28));
- al = singleElement(al);
- Iterator it = al.iterator();
- while(it.hasNext())
- {
- Object obj = it.next();
- Person p = (Person)obj; //需要强转型为Person类才能调用方法;
- System.out.println(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是一致的。
Set的两个常用子集:HashSet、treeSet。
3.1、HashSet
HashSet:底层数据结构式哈希表。线程是非同步的。
HashSet保证元素唯一性是通过元素的两个方法hashCode和equals来完成的,如果元素的hashCode值相同才会判断equals是否为true,如果元素的hashCode值不同,则不会调用equals方法。
注意:对于判断元素是否存在(contains)以及删除(remove)等操作,依赖的方法是元素的hashCode和equals方法。
3.2、TreeSet
TreeSet:底层数据结构式二叉树,可以对Set集合中的元素进行排序。
TreeSet保证元素唯一性的依据是compareTo方法return 0.
TreeSet的第一种排序方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。该顺序也被称为元素的自然顺序或者默认顺序。
示例:
- import java.util.*;
- class TreeSetDemo
- {
- public static void main(String[] args)
- {
- TreeSet ts = new TreeSet();
- ts.add(new Student("java04",25));
- ts.add(new Student("java01",12));
- ts.add(new Student("java05",12));
- ts.add(new Student("java02",18));
- ts.add(new Student("java03",22));
- Iterator it = ts.iterator();
- while(it.hasNext())
- {
- Student s = (Student)it.next();
- System.out.println(s.getName()+"..."+s.getAge());
- }
- }
- }
- class Student implements Comparable//让Student实现Comparable接口,
- { //使之具有比较性;
- private String name;
- private int age;
- Student(String name,int age)
- {
- this.name = name;
- this.age = age;
- }
- public int compareTo(Object obj)//覆盖Comparable中的compareTo方法;
- {
- 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;
- }
- public String getName()
- {
- return name;
- }
- public int getAge()
- {
- return age;
- }
- }
TreeSet的第二种排序方式:当元素自身不具备比较性时,或者具备的比较性不是所需的时,这时就需要让集合自身具备比较性。 实现方式:在集合初始化时,就让其具备比较性。即定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
定义比较器的方法:定义一个类实现Comparator接口,覆盖其Compare方法。
示例:
- import java.util.*;
- class TreeSetDemo1
- {
- public static void main(String[] args)
- {
- TreeSet ts = new TreeSet(new MyCompare());//将比较器对象作为参数传递给
- ts.add(new Student("java01",12)); //TreeSet集合的构造函数,让集合具有比较性;
- ts.add(new Student("java01",18));
- ts.add(new Student("java05",28));
- ts.add(new Student("java03",20));
- ts.add(new Student("java04",16));
- ts.add(new Student("java02",35));
- Iterator it = ts.iterator();
- while(it.hasNext())
- {
- Student s = (Student)it.next();
- System.out.println(s.getName()+"::"+s.getAge());
- }
- }
- }
- class Student
- {
- private String name;
- private int age;
- Student(String name,int age)
- {
- this.name = name;
- this.age= age;
- }
- public String getName()
- {
- return name;
- }
- public int getAge()
- {
- return age;
- }
- }
- class MyCompare implements Comparator//定义一个比较器,让其实现Comparator接口;
- {
- public int compare(Object o1,Object o2)//覆盖Comparator中的compare方法,
- { //让其按照我们自定义的放将对象进行比较;
- 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()));
- return num; //将学生的年龄进行封装,再做比较;
- }
- }
当两种方式都存在时,以比较器为主。
注意:排序时,当主要条件相同时,一定要判断一下次要条件。