三大集合特点

来源:互联网 发布:淘宝水印怎么批量设置 编辑:程序博客网 时间:2024/04/30 07:14

一、Set集合,其主要实现类有HashSet、TreeSet。存放对象的引用,不允许有重复对象。
通过java的equals()方法判别。如果有特殊需求须重载equals()方法。
1、HashSet(),调用对象的hashCode()方法,获得哈希码,然后再集合中计算存放对象的位置。通过比较哈希码与equals()方法来判别是否重复。所以,重载了equals()方法同时也要重载hashCode()方法。
2、TreeSet(),继承ShortedSet接口,能够对集合中对象排序。默认排序方式是自然排序,但该方式只能对实现了Comparable接口的对象排序,java中对Integer、Byte、Double、Character、String等数值型和字符型对象都实现了该接口。
如果有特殊排序,须重载该接口下的compareTo()方法或通过Comparator接口的实现类构造集合。
二、List集合,其主要实现类有LinkedList、ArrayList,前者实现了链表结构,后者可代表大小可变的数组。List的特点是能够以线性方式储蓄对象,并允许存放重复对象。List能够利用Collections类的静态方法sort排序。sort(List list)自然排序;sort(List listm,Comparator comparator)客户化排序。
三、Map集合,其主要实现类有HashMap、TreeMap。Map对值没有唯一性要求,对健要求唯一,如果加入已有的健,原有的值对象将被覆盖。HashMap类按照哈希算法来存取键对象,可以重载equals()、hashCode()方法来比较键,但是两者必须一致。TreeMap,可自然排序,也可通过传递Comparator的实现类构造TreeMap。
(1)集合的由来?
我们学习的是Java – 面向对象 – 操作很多对象 – 存储 – 容器(数组和StringBuffer) – 数组
而数组的长度固定,所以不适合做变化的需求,Java就提供了集合供我们使用。
(2)集合和数组的区别?
A:长度区别
数组固定
集合可变
B:内容区别
数组可以是基本类型,也可以是引用类型
集合只能是引用类型
C:元素内容
数组只能存储同一种类型
集合可以存储不同类型(其实集合一般存储的也是同一种类型)
(3)集合的继承体系结构?
由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,
我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。

Collection:
|–List 有序(元素存入集合的顺序和取出的顺序一致),元素都有索引,而且元素可以重复。
|–ArrayList
|–Vector
|–LinkedList
|–Set 无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性。
|–HashSet
|–TreeSet
Collection的功能:
A:添加功能
boolean add(Object obj):向集合中添加一个元素
boolean addAll(Collection c):向集合中添加一个集合的元素
B:删除功能
void clear():删除集合中的所有元素
boolean remove(Object obj):向集合中删除指定的元素
booleanremoveAll(Collection c):向集合中删除一个指定的集合元素
C:判断功能
boolean isEmpty():判断集合是否为空
boolean contains(Object obj):判断集合中是否存在指定的元素
boolean containsAll(Collection c):判断集合中是否存在指定的元素
D:遍历功能
Iterator iterator():就是用来获取集合中每一个元素
E:长度功能
int size():获取集合中的元素个数
F:交集功能
boolean retainAll(Collection c):判断两个集合中是否有相同的元素
G:转换功能
Object[] toArray():把集合变成数组
小练习:遍历集合中的元素,判断是否存在元素“hello”。

/* * 请遍历集合:也就是获取到集合中的每一个元素。 * 判断集合中是否存在"hello"这个元素. * 注意: *      在往集合中添加元素的时候,集合默认接收的是Object类型。 *      也就是说你开始存储字符串的时候,其实做了一个向上转型的操作。 *  *      在获取元素的时候,默认还是以Object类型的返回。 *      但是,你明明知道这应该是String类型。 *      所以,如果你想使用String类型的特殊功能,就必须做向下转型。 *      如果仅仅是为了看结果,就不用。因为通过多态的形式,最终输出语句调用的是String类的toString() */public class CollectionDemo2 {    public static void main(String[] args) {                flag=true;   //元素标记符,        Collection c = new ArrayList(); //创建集合对象                // 添加元素        c.add("hello"); // String -- Object        c.add("world");        c.add("java");        // 直接使用判断功能        // System.out.println("contains:"+c.contains("hello"));        // System.out.println("c:" + c);//若存在,则会输出true        // 遍历集合,获取到每一个元素,然后判断这个元素是否是hello        // Object[] toArray():把集合变成数组。        Object[] objs = c.toArray();        for (int x = 0; x < objs.length; x++) {               //将Object类型的数组强制转换为String类型            String s = (String) objs[x];                            if(s.equals("hello")){                                flag=true;            //如果存在,就输出真,否则输出假                             }else{                                 flag=false;                             }            System.out.println(s + "***" + s.length()+"***"+flag);        }    }}

小练习:用迭代器遍历集合中的元素。

/* * 成员方法: *      Object next():获取元素,并自动移动到下一个位置等待获取。 *      boolean hasNext():判断迭代器中是否还有元素。  * NoSuchElementException:没有这样的元素异常。你已经获取到元素末尾了,你还要获取,已经没有元素了。所以报错了。 */public class IteratorDemo {    public static void main(String[] args) {        // 创建对象        Collection c = new ArrayList();        // 添加元素        c.add("hello");        c.add("world");        c.add("java");        // 方式1        // Object[] objs = c.toArray();        // for (int x = 0; x < objs.length; x++) {        // String s = (String) objs[x];        // System.out.println(s);        // }// 方式2      // Iterator iterator():就是用来获取集合中每一个元素。        // 通过集合对象获取迭代器对象        Iterator it = c.iterator();// 这是返回的是Iterator的子类对象,多态        while (it.hasNext()) {            // System.out.println(it.next());            String s = (String) it.next();            System.out.println(s);        }   }  }

list接口

 List本身是Collection接口的子接口,具备Collection的所有方法。现在学习list体系特有的共性方法,查阅方法发现List的特有方法都有索引,这是该集合最大的特点。

1)List特有功能:
A:添加功能
void add(int index,Object obj):在指定位置添加元素
B:删除功能
Object remove(int index):根据指定索引删除元素,并把删除的元素返回
C:修改功能
Object set(int index,Object obj):把指定索引位置的元素修改为指定的值,返回修改前的值。
D:获取功能
Object get(int index):返回指定元素在集合中第一次出现的索引
int indexOf(Object obj):获取指定位置的元素,如果该元素不存在返回-1;所以,通过-1,可以判断一个元素是否存在 int lastIndexOf(Object obj):反向索引指定元素的位置
List subList(start,end):获取子列表
ListIterator listIterator():列表迭代器(List集合特有的迭代器)
2)List的遍历方式
A:Iterator 迭代器
B:ListIterator迭代器(了解)
C:普通for(和list的get方法使用)
3)ListIterator迭代器
A:是Iterator的子接口。
B:有自己的特有功能,可以逆向遍历数据,但是需要先正向遍历。一般不用。

/* * ListIterator listIterator():列表迭代器 *  * boolean hasNext() * Object next() *  * 特有功能: * boolean hasPrevious()         * Object previous()  *  * 虽然,可以逆向遍历,但是,要求先正向遍历,然后才能逆向遍历。 */public class ListDemo5 {    public static void main(String[] args) {        // 创建集合对象        List list = new ArrayList();        // 添加元素        list.add("hello");        list.add("world");        list.add("java");        // 遍历        ListIterator lit = list.listIterator();        while (lit.hasNext()) {            String s = (String) lit.next();            System.out.println(s);        }        System.out.println("----------------");        // System.out.println(lit.previous());        // System.out.println(lit.previous());        // System.out.println(lit.previous());        // // NoSuchElementException        // System.out.println(lit.previous());        // 逆向遍历        while (lit.hasPrevious()) {            String s = (String) lit.previous();            System.out.println(s);        }    }}

4)面试题:并发修改异常
A:并发修改异常的产生原因:用迭代器遍历集合,用集合去操作集合。
B:解决方案:a:使用集合操作。
b:使用列表迭代器操作。
代码如下:

import java.util.ArrayList;import java.util.List;import java.util.ListIterator;/* * ListIterator listIterator():列表迭代器 *  * public interface ListIterator extends Iterator *  * 面试题:ConcurrentModificationException:并发修改异常。 *      这是个什么异常,怎么产生的,怎么解决的?  * 怎么产生: *      当我们通过迭代器迭代元素的过程中,又通过集合去添加了元素。这种情况是不允许的。 *      因为迭代器是依赖于集合存在的,如果集合发生改变,迭代器也应该相应的发生改变。 *      而我们目前看到的确实,迭代器没变,集合变了。所以,报出了一个并发修改异常。 *  * 注意问题:通过迭代器遍历集合的时候,是不能通过集合去操作(添加,删除)。 * 那么,我们可不可以这样理解呢? * A:全部通过迭代器操作:元素是添加到刚遍历的那个元素后面。 *      通过迭代器迭代的时候,可以通过迭代器对集合进行操作。 * B:全部通过集合操作:元素是添加到最后的。 *      通过集合普通for遍历的时候,可以通过集合去操作。 */public class ListDemo4 {    public static void main(String[] args) {        // 创建集合对象        List list = new ArrayList();        // 添加元素        list.add("hello");        list.add("world");        list.add("java");        // 迭代器        // Iterator it = list.iterator();        // while (it.hasNext()) {        // String s = (String) it.next();        // System.out.println(s);        // }        // System.out.println("-----------");        // 需求:请遍历集合,判断其中是否有"hello"这个元素,如果有,就再添加一个元素:"IOS"        // Iterator it = list.iterator();        // while (it.hasNext()) {        // String s = (String) it.next();        // if ("hello".equals(s)) {        // list.add("IOS");        // // it = list.iterator();//这样从原理是可以解决的,但是它会引起另外一个问题。        // }        // }        // System.out.println("list:" + list);        // System.out.println("-----------");        // 完全通过集合实现        // for (int x = 0; x < list.size(); x++) {        // String s = (String) list.get(x);        // if ("hello".equals(s)) {        // list.add("IOS");        // }        // }        // System.out.println("list:"+list);        // System.out.println("-----------");        // 遍历        ListIterator lit = list.listIterator();        while (lit.hasNext()) {            String s = (String) lit.next();            if ("hello".equals(s)) {                lit.add("IOS");            }        }        System.out.println("list:" + list);    }}

5)List:
|–ArrayList:底层数据结构是数组,线程不安全(即不同步),它的出现替代了Vector,增删的效率很慢,但是查询的效率很高。
|–Vector:底层数据结构是数组,线程安全,无论增删还是查询都非常慢。
|–LinkedList:底层是链表,线程不安全,对元素的增删的操作效率很高,查询效率低。

ArrayList的小练习:
需求:我现在用ArrayList存储多个字符串元素。
比如说数据如下:hello,world,java,hello,.net,java,php,IOS,java,android
我要求你写程序,实现去除重复元素。也就是说结果是:hello,world,java,.net,php,IOS,android

 5)List:   |--ArrayList:底层数据结构是数组,线程不安全(即不同步),它的出现替代了Vector,增删的效率很慢,但是查询的效率很高。   |--Vector:底层数据结构是数组,线程安全,无论增删还是查询都非常慢。   |--LinkedList:底层是链表,线程不安全,对元素的增删的操作效率很高,查询效率低。ArrayList的小练习:需求:我现在用ArrayList存储多个字符串元素。   比如说数据如下:hello,world,java,hello,.net,java,php,IOS,java,android 我要求你写程序,实现去除重复元素。也就是说结果是:hello,world,java,.net,php,IOS,android

方法二:

  /* * 在同一个集合上操作:双层循环实现 *      第一方式没有问题,第二种可能有问题。 *      但是,第二种的问题也是可以解决的? *      怎么解决呢? *      把每次删除掉元素的那个位置,在回来比较一次即可。 */public class ArrayListTest2 {    public static void main(String[] args) {        // 创建旧集合,并添加元素        ArrayList array = new ArrayList();        array.add("hello");        array.add("world");        array.add("java");        array.add("hello");        array.add(".net");        array.add("java");        array.add("java");        array.add("java");        array.add("php");        array.add("IOS");        array.add("java");        array.add("android");        // 这下面的代码和选择排序类似。理解即可。最好通过断点看过程。        for (int x = 0; x < array.size() - 1; x++) {            for (int y = x + 1; y < array.size(); y++) {                if (array.get(y).equals(array.get(x))) {                    array.remove(y);                    y--;                }            }        }        // 遍历        Iterator it = array.iterator();        while (it.hasNext()) {            String s = (String) it.next();            System.out.println(s);        }    }}

下面是一个面试题:用ArrayList存储学生,如何去除重复的元素?

“`
import java.util.ArrayList;
import java.util.Iterator;

/*
* ArrayList如果存储的是学生,那么,怎么去除重复元素呢?
* 问题:如何知道学生是重复的。
* 需求:如果学生的姓名和年龄相同,我就认为是同一个学生。即重复值。
*
* 通过简单分析,我们估计是判断那里出问题了。
* 怎么办呢?
* 看判断的方法。
* 而我们又知道,判断的方法是API提供的。不是自己的写的。
* 看源码,看底层到底怎么实现的。
* 通过看源码,我们发现,底层依赖的是equals()。
* 由于学生类中,我们并没有equals()方法,所以,默认用的是Object的方法。
* 而Object类的方法,默认比较的是地址值。
* 由于学生对象都是new出来的,地址值肯定不一样,所以从这个角度考虑结论是正确的。
* 但是不符合我们的需求。
* 肿么办?
* 重写equals(),让他按照我们的需要来比较。
*/

//标准学生类
public class Student {
//定义两个成员变量
private String name;
private int age;

public Student() {}public Student(String name, int age) {    this.name = name;    this.age = 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;}   //重写equals方法@Overridepublic boolean equals(Object obj) {    // 提高效率    if (this == obj) {        return true;    }    // 提高健壮性    if (!(obj instanceof Student)) {        return false;    }    // 向下转换    Student s = (Student) obj;    return this.name.equals(s.name) && this.age == s.age;}

}

public class ArrayListTest3 {
public static void main(String[] args) {
ArrayList array = new ArrayList();

    Student s1 = new Student("301宿舍--笨笨", 22);    Student s2 = new Student("301宿舍--姗姗", 23);    Student s3 = new Student("301宿舍--姗姗", 30);    Student s4 = new Student("301宿舍--红红", 20);    Student s5 = new Student("301宿舍--红红", 20);    Student s6 = new Student("301宿舍--蛋蛋", 24);            Student s7 = new Student("301宿舍--媛媛", 22);            Student s8 = new Student("301宿舍--歪歪", 23);    array.add(s1);    array.add(s2);    array.add(s3);    array.add(s4);    array.add(s5);    array.add(s6);    // 创建新集合    ArrayList array2 = new ArrayList();    // 遍历旧集合,获取到每一个元素    Iterator it = array.iterator();    while (it.hasNext()) {        Student s = (Student) it.next();        // 在新集合中判断,看是否存在这个元素        if (!array2.contains(s)) {            // 如果s不再array2中存在,就添加            array2.add(s);        }    }    // array2就是没有重复元素的集合。    // 遍历array2    for (int x = 0; x < array2.size(); x++) {        Student s = (Student) array2.get(x);        System.out.println(s.getName() + "***" + s.getAge());    }}

}

“`这里写图片描述

1 0