集合的介绍和使用

来源:互联网 发布:豆瓣fm windows 编辑:程序博客网 时间:2024/06/07 11:40

集合的结构图

这里写图片描述
这里写图片描述

集合框架

List集合面试两大陷阱:

1.用for循环一边遍历一边删除
删除不干净:一边遍历一边删除,集合角标每次再自增1,而每次删除一个元素后集合下标和大小size会改变,所以只可以删除一半的元素
2.数组转换集合
Arrays.asList–返回值是Arrays类的一个静态内部类,而这个内部类不支持增加和修改,只能支持查看和修改

这里写图片描述

Vector是同步的,线程安全
ArrayList是异步的,线程不安全

Collection是List和Set的父接口
Collections是集合的工具类

*集合中存储的都是对象的地址

Collection分为两大类:List和Set
List:元素是有序的,元素可以重复,因为该集合体系有下标
Set:元素是无序的,元素不可以重复,因为该集合体系没有下标

①List又包含三种类型的数据存储容器:ArrayList、 LinkedList 和Vector
–ArrayList:底层的数据结构使用的是数组结构,线程不同步,默认长度大小为10,当不够用时每次增长度的50%。
特点:查询 速度很快,但是增删稍慢
–LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询慢
–Vector:底层使用的也是数组数据结构,线程同步。默认长度大小为10,当不够用时每次增长度的100%。 被ArrayList替代了
Set包含两种数据存储容器类型:HashSet和TreeSet

②List集合特有的迭代器。ListIterator是Iterator的子接口。在迭代时,不可以通过集合对象的方法操作集合中的元素,会发生ConcurrentModificationException异常。所以,在使用迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的。只有三个方法:hasNext( )判断是否存在下一个元素、next( )取下一个元素、remove( )移除元素引用的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口ListIterator,该接口中有许多Iterator接口中不存在的方法,且该接口只能通过List集合的listIterator方法获取

Set下面的集合:

一、TreeSet(即排序,又查重):

① 比较器的实现
查重标准:比较器接口中自己定义规则
set集合中的自定义对象都要实现比较器接口Comparable(),覆写里面的compareTo()方法。
如果放入set集合中的类型无法在其本类中实现比较器接口,那么要通过第三方类实现比较的功能,则在此第三方类中实现Comparator接口,并覆写其中的compare()方法,则此时在TreeSet的参数里面传入实现Comparator接口的类对象

compareTo()和compare()方法中当前类对象的某个属性大于另外一个对象的相同属性是,return 1,如果小于的话return -1;如果相同的话return 0

实现代码例子:

package TreeSet;import java.util.Comparator;public class Person {    String name;    int age;    public Person(String name, int age){        this.name = name;        this.age = age;    }    @Override    public int compareTo(Person o) {        if(this.age > o.age){            return 1;        }        if(this.age < o.age){            return -1;        }        return this.name.compareTo(o.name);    }    @Override    public String toString() {        // TODO Auto-generated method stub        return this.name + "    " + this.age;    }}

二、HashSet(只查重,不排序)

hashCode是定义在Object中的方法,根据对象的地址动态计算出一个值

如果set集合中的放入的是引用数据类型,则查重标准为:
①hashCode: 首先调用hashCode方法进行HashCode值的比较。也就是==比较,因为hashCode方法就是和地址有关
所以调用父类的hashCode方法没有意义,需要覆写

②equals:如果两个对象hashCode值一样,调用equals,比较的是地址,所以也无意义,因为比较地址就是比较hashCode的值。所以要对equals方法进行覆写

总而言之,当两个对象的hashCode值相同时,就调用equals方法再进行各项属性之间的比较。如果hashCode值不同时,则就不再需要进行equals比较。

代码例子:

package HashSet;public class Person {    String name;    int age;    public Person(String name, int age){        this.name = name;        this.age = age;    }    @Override    public int hashCode() {        int x1 =  age*31;        int x2 = name.length()*78;        return x1*x2;    }    @Override    public boolean equals(Object obj) {        Person p = (Person) obj;        boolean flag1 = name.equals(p.name);        boolean flag2 = age==p.age;        return flag1 && flag2;    }    @Override    public String toString() {        // TODO Auto-generated method stub        return this.name + "    " + this.age;    }}

Map下面的集合:(Map中键都不允许重复)

 Map分为hashMap和TreeMap      

一、TreeMap(键不允许为空,值可以为空)
treeMap中键不允许重复

在自定义对象类中实现比较器接口Comparable或着在第三方类中实现Comparable接口,覆写其中的comparaTo()方法进行查重和比较

二、hashMap(键和值都可以为空null)
hashMap只可以实现查重,不可以实现排序,它和HashSet一样,都是通过类对象覆写hashCode()和equals()方法来实现通过具体的属性进行查重。

Hashtable:底层是哈希表数据结构,不可以存入null键、null值。该集合时线程同步的

HashMap:底层是哈希表数据结构,允许使用bull值和null键,该集合是不同步的

map集合的两种取出方式:
Map集合的取出原理:将map集合转成set集合,再通过迭代器取出。
1.keyset:返回类型是Set。将map中的所有的键存入到Set集合。因为set具备迭代器,所以可以用迭代器方式取出所有的键,再根据get方法,获取每一个键对应的值
2.entrySet:返回类型是Set

   public static void main(String[] args) {        Map<String, String> map = new HashMap<String, String>();        map.put("06", "java06");        map.put("03", "java03");        Set<String> keySet = map.keySet();        Iterator<String> it = keySet.iterator();        while(it.hasNext()){            String key = it.next();            String value = map.get(key);            System.out.println("Key:" + key + "  Value:" + value);        }    }

entrySet图例:
这里写图片描述
entrySet代码样例:

public static void main(String[] args) {        Map<String, String> map = new HashMap<String, String>();        map.put("05", "java05");        map.put("02", "java02");        Set<Map.Entry<String, String>> entrySet = map.entrySet();        Iterator<Map.Entry<String, String>> it = entrySet.iterator();        while(it.hasNext()){            Map.Entry<String, String> me = it.next();            String key = me.getKey();            String value = me.getValue();            System.out.println("key:" + key + " value:" + value);        }    }

Entry<K, V>是一个接口,是Map<K, V>接口中的内部接口,是用static修饰符所修饰的静态内部接口,用来存放映射项(键-值对)

TreeSet、HashSet、TreeMap和HashMap的代码实现:
主函数类:

public class Test {    /**     * HashMap只可以查重,不可以排序     *        和HashSet一样,都是需要覆写hashCode和equals方法进行查重     */    public static void main(String[] args) {        HashMap<String,Person> map = new HashMap<>();        map.put("xx2", new Person("张三2",18));        map.put("xx1", new Person("张三1",12));        map.put("xx5", new Person("张三5",13));        map.put("xx1", new Person("张三1",15));        map.put("xx7", new Person("张三7",16));        map.put("xx6", new Person("张三7",16));        map.put("xx3", new Person("张三3",14));        Set<String> key = map.keySet();        Iterator<String> it = key.iterator();        while(it.hasNext()){            String k = it.next();            Person p = map.get(k);            System.out.println("键:" + k + "   学生:" + p);        }    }
/**     * TreeMap:可以查重和排序     *         在将数据放入集合中以后可以通过Set集合将map集合中的键存入set集合中     *         用的是keySet方法,在通过Set的迭代器将键的和遍历     *         通过while循环取出键,再通过键在map集合中取出该键对应的值。     */    public static void main3(String[] args) {        TreeMap<String,Person> map = new TreeMap<>();        map.put("xx2", new Person("张三2",18));        map.put("xx1", new Person("张三1",12));        map.put("xx5", new Person("张三5",13));        map.put("xx1", new Person("张三1",15));        map.put("xx7", new Person("张三7",16));        map.put("xx6", new Person("张三7",16));        map.put("xx3", new Person("张三3",14));        Set<String> key = map.keySet();        Iterator<String> it = key.iterator();        while(it.hasNext()){            String k = it.next();            Person p = map.get(k);            System.out.println("键:" + k + "   学生:" + p);        }    }    /**     * HashSet集合中只可以进行查重,不可以进行排序。     */    public static void main2(String[] args) {        HashSet<Person> set = new HashSet<>();        set.add(new Person("xx2",12));        set.add(new Person("xx6",16));        set.add(new Person("xx9",19));        set.add(new Person("xx3",13));        set.add(new Person("xx2",12));        set.add(new Person("xx1",11));        set.add(new Person("xx3",13));        Iterator it = set.iterator();        while(it.hasNext()){            System.out.println(it.next());        }    }    /**     * TreeSet:Set集合含有迭代器,可以进行集合的遍历     *         可以进行排序和查重     */    public static void main1(String[] args) {        TreeSet<Person> set = new TreeSet<>();        set.add(new Person("xx2",12));        set.add(new Person("xx6",16));        set.add(new Person("xx9",19));        set.add(new Person("xx3",13));        set.add(new Person("xx2",12));        set.add(new Person("xx1",11));        set.add(new Person("xx3",13));        Iterator it = set.iterator();        while(it.hasNext()){            System.out.println(it.next());        }    }
//对象类:public class Person {    String name;    int age;    public Person(String name, int age){        this.name = name;        this.age = age;    }    @Override    public String toString() {        return "name:" + name + "    age:" + age;    }      // HashMap只可以查重,不可以排序      //通过覆写hashCode和equals方法进行查重    @Override    public int hashCode() {        int x1 = name.length()*78;        int x2 = age*31;        return x1*x2;    }    @Override    public boolean equals(Object obj) {        Person per = (Person)obj;        boolean flag = this.name.equals(per.name);        boolean flag1 = this.age == per.age;        return flag && flag1;    }
     //TreeMap:可以进行排序和查重,其中必须是键不相同,不同的键有相同的值是可以的     //        需要实现比较器接口     //        implements Comparable<Person>    @Override    public int compareTo(Person o) {        if(this.age > o.age){            return 1;        }        if(this.age < o.age){            return -1;        }        else{            return this.name.compareTo(o.name);        }    }
     // HashSet:只可以查重,不可以排序.     //        通过在对象类中覆写hashCode()和equals()方法     //        先通过hashCode方法进行查重,不相同直接返回;     //         相同则执行equals方法进行查重    @Override    public int hashCode() {        int x1 = name.length()*78;        int x2 = age*31;        return x1*x2;    }    @Override    public boolean equals(Object obj) {        Person per = (Person)obj;        boolean flag = this.name.equals(per.name);        boolean flag1 = this.age == per.age;        return flag && flag1;    }
     // TreeSet:可以排序,也可以查重,通过实现Comparable接口,     //         如果本类实现不了的话则选择在第三方的类中实现Comparator接口     //implements Comparable<Person>    @Override    public int compareTo(Person o) {        if(this.age > o.age){            return 1;        }        if(this.age < o.age){            return -1;        }        else{            return this.name.compareTo(o.name);        }    }

0 0