day_14~16:集合框架

 集合

  1.集合是Java API所提供的一系列类,可以用于动态存放多个对象。--》集合只能存对象

  2.集合与数组的不同在于,集合是大小可变的序列,而且元素类型可以不受限制,只要是引用类型。(集合中不能放基本数据类型,但可以放基本数据类型的包装类)

  3.集合类全部支持泛型,是一种数据安全的用法。

集合框架图

  Java的集合框架从整体上可以分为两大家族:

1.Collection(接口)家族。该接口下的所有子孙均存储为单一对象。  Add(s)

2.Map(接口)家族。该接口下的所有子孙均存储的是key-value(键值对)形式的数据。  Put(key, value)

  另外还有三个分支,均是为上述两个家族服务的。

1.Iterator(迭代器)家族。主要用于遍历Collection接口及其子类而设计。

2.Comparator(比较器),在集合中存储对象时候,用于对象之间的比较

3.Collections是工具类。注意该类带个s,一般就表示工具类。里面提供了N多静态方法,来对Collection集合进行操作。

Collection

  List:有序(录入的顺序跟输出的顺序一致),可重复,存储单个元素  --》方法中添加了index参数,从 0 开始

    ArrayList:      数据结构: 一维数组

    LinkedList:       数据结构:双向链表

    Vection:         数据结构:一维数组

    Stack(继承Vector): 数据结构:一维数组  特点:栈的数据结构

ArrayList VS LinkedList (两个集合的使用方法一模一样)

  区别:1.队列模式或栈模式就用LinkedList

     2. ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构;

     3.效率:

        添加:一样快

        插入:LinkedList快

        删除:LinkedList快

        查询:ArrayList快(因为ArrayList有下标)

  ps:平时如果不用到队列模式(先进先出)或栈模式(先进后出)就用ArrayList,因为项目中往往查询比其他功能用的更频繁

Vector VS ArrayList

  数据结构都是一维数组,但是Vector线程安全,ArrayList线程不安全         

  Set:无序(元素存入的顺序与取出的顺序不同,但是每次取出的顺序是一致的,无序不代表随机),不可重复

    HashSet:  数据结构:Hash数组  应用场景:元素去重

    TreeSet:

Map --- 集合(接口)

  特点:键值对存储 K-V

    HashMap:  数据结构:Hash数组  特点:key是唯一的,value可以重复

    HashTable:

    ConcurrentHashMap:

    TreeMap:

List实现类之ArrayList

  ArrayList和Array的区别:容量可扩展性、存储的必须是对象;

ArrayList的方法

  一般情况newArrayList对象使用:ArrayList<E> array = new ArrayList<>();  当我们需要用到List的其他实现类时就使用:List<E> list = new ArrayList<>();

public class Test {

    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>();
        
        //添加元素
        list.add("赤名莉香");
        list.add("关口里美");
        list.add("长崎尚子");
        list.add("赤名莉香");
        list.add("永尾完治");
        list.add("三上健一");
        list.add("赤名莉香");
        
        System.out.println("获取第一个元素:"+list.get(0));
        System.out.println("获取该集合长度:"+list.size());
        System.out.println("判断集合内是否有指定元素:"+list.contains("赤名莉香"));
        System.out.println("集合内没有元素吗?"+list.isEmpty());
        System.out.println("查询置顶元素在集合中第一次出现的位置:"+list.indexOf("赤名莉香"));
        System.out.println("查询指定元素在集合中最后一次出现的位置:"+list.lastIndexOf("赤名莉香"));
        
        //替换
        list.set(3, "和贺夏树");
        
        //插入
        list.add(3, "渡边");
        
        //删除
        list.remove(1);
        
        //遍历--for
        for(int i=0;i<list.size();i++) {
            System.out.println(list.get(i));
        }
        
        System.out.println("----------------------");
        //遍历--foreach
        for (Object object : list) {
            
            System.out.println(object);
        }
        System.out.println("----------------------");
        //遍历--迭代器
        Iterator<Object> iterator = list.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }    
    }
}
ArrayList的方法
public class Test03 {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("赤名莉香");
        list.add("关口里美");
        list.add("长崎尚子");
        list.add("赤名莉香");
        list.add("永尾完治");
        list.add("三上健一");
        list.add("赤名莉香");

        // 遍历删除
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String string = iterator.next();
            if (string.equals("关口里美")) {
                iterator.remove();// 删除指定指针
            }
        }
        for (String string : list) {
            System.out.println(string);
        }
    }

}
ArrayList遍历删除
public class Test04 {
    
    public static void main(String[] args) {
        
        //特殊点:
        
        ArrayList<Integer> list = new ArrayList<>();
        
        //自动装箱
        list.add(1);//list.add(Integer.valueOf(1));
        list.add(2);
        list.add(3);
        list.add(4);
        
        //以元素删除 --- 手动装箱
        list.remove(Integer.valueOf(2));
        
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()) {
            Integer integer = it.next();
            System.out.println(integer);
        }
    }
}
自动装箱,手动拆箱

List实现类之LinkedList

  与ArrayList的用法一模一样,多了队列模式和栈模式

public class Test01 {

    public static void main(String[] args) {
        
        /**
         * 队列模式:先进先出
         */
         LinkedList<String> list = new LinkedList<>();
         
         list.add("赤名莉香1");
         list.add("赤名莉香2");
         list.add("赤名莉香3");
         list.add("赤名莉香4");
         
         while(!list.isEmpty()) {
             //删除列表中的第一个元素,并返回
             String removeFirst = list.removeFirst();
             System.out.println(removeFirst);
         }
    }
}
队列模式
public class Test02 {

    public static void main(String[] args) {
        
        /**
         * 栈模式:先进后出
         */
         LinkedList<String> list = new LinkedList<>();
         
         list.add("赤名莉香1");
         list.add("赤名莉香2");
         list.add("赤名莉香3");
         list.add("赤名莉香4");
         
         while(!list.isEmpty()) {
             //删除列表中的最后一个元素,并返回
             String removeFirst = list.removeLast();
             System.out.println(removeFirst);
         }
    }
}
栈模式

LinkedList源码分析

分析源码:
    1.找入口
    2.看主线
    
    
-----------------------LinkedList.class-------------------------
    廖佳星    夏凡       舒老师    
    
    transient Node<E> first;
    
    transient Node<E> last;

    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
    
-----------------------LinkedList$Node.class-------------------------
    
    private static class Node<E> {
        E item;        ----- 元素
        Node<E> next; --- 下一个节点的地址
        Node<E> prev; --- 上一个节点的地址

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
LinkedList源码分析

List实现类之Vector

public class Test02 {
    
    public static void main(String[] args) {
        
        Vector<String> vector = new Vector<>();
        
        vector.addElement("麻生希1");
        vector.addElement("麻生希2");
        vector.addElement("麻生希3");
        vector.addElement("麻生希4");
        
        vector.setElementAt("桃谷绘里香", 1);
        
        vector.removeElement("麻生希3");
        vector.removeElementAt(2);
        
        Enumeration<String> elements = vector.elements();
        while(elements.hasMoreElements()){
            String nextElement = elements.nextElement();
            System.out.println(nextElement);
        }
        
    }

}
古老的方法

List实现类之Stack

public class Test01 {
    
    public static void main(String[] args) {
        
        Stack<String> stack = new Stack<>();
        
        //把项压入栈顶(添加)
        stack.push("夏凡1");
        stack.push("夏凡2");
        stack.push("夏凡3");
        stack.push("夏凡4");
        
        //遍历
        while(!stack.empty()){
            String pop = stack.pop();
            System.out.println(pop);
        }
    }

}
方法

Map实现类之HashMap

 HashMap的方法

public class Test01 {
    
    public static void main(String[] args) {
        
        HashMap<String, Integer> map = new HashMap<>();
        
        //添加
        map.put("麻生希", 23);
        map.put("天海翼", 26);
        map.put("小泽玛利亚", 28);
        map.put("泷泽萝拉", 21);
        map.put("北川瞳", 27);
        
        //替换
        map.put("泷泽萝拉", 888);
        
        //删除(通过key删除映射关系)
        map.remove("北川瞳");
        
        System.out.println("通过key获取到指定的值:" + map.get("天海翼"));
        System.out.println("判断此集合是否有指定key:" + map.containsKey("天海翼"));
        System.out.println("判断此集合是否有指定value:" + map.containsValue(21));
        System.out.println("判断此集合中是否没有元素:" + map.isEmpty());
        System.out.println("获取此集合中映射关系的个数为:" + map.size());
        
        //遍历思路一:把map集合中的所有key取出放在set集合里,遍历set集合依次取出key,就可以取出key对应的value
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            Integer value = map.get(key);
            System.out.println(key + " -- " + value);
        }
        System.out.println("---------------------");
        
        //遍历思路二:把map集合中的所有“映射关系”取出放在set集合里
        //(映射关系就是Entry类的对象,对象中有两个重要属性:key、value)
        Set<Entry<String, Integer>> entrySet =  map.entrySet();
        for (Entry<String, Integer> entry : entrySet) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " -- " + value);
        }
    }

}
hashmap的方法

判断一个字符串里字符出现的次数

public class Test03 {

    public static void main(String[] args) {
        
        //判断一个字符串里字符出现的次数???
        String str = "123123abcdcdefg12";
        
        char[] charArray = str.toCharArray();
        
        HashMap<Character, Integer> map = new HashMap<>();
        
        for (char c : charArray) {
            if(map.get(c) == null){
                map.put(c, 1);
            }else{
                map.put(c, map.get(c)+1);
            }
        }
        Set<Entry<Character,Integer>> entrySet = map.entrySet();
        for (Entry<Character, Integer> entry : entrySet) {
            Character key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " -- " + value);
        }
        
        /**
         * 思考题:HashSet底层由HashMap实现,
         *         HashSet是存一个值,HashMap是存两个值
         *         结合两个集合的特点,分析出HashSet存值是存在底层的HashMap里的key还是value的位置??
         */
        
    }
}
判断一个字符串里字符出现的次数

Set实现类之HashSet

方法和HashMap一样

Set实现类之TreeSet

TreeSet常用方法及Integer类型排序:数字升序

public class Test01 {
    
    public static void main(String[] args) {
        
        /**
         * TreeSet存入Integer类型排序规则是:数字升序
         */
        
        TreeSet<Integer> set = new TreeSet<>();
        
        set.add(2);
        set.add(1);
        set.add(4);
        set.add(3);
        
        System.out.println("判断此集合是否有指定元素:" + set.contains(2));
        System.out.println("判断此集合是否没有元素:" + set.isEmpty());
        System.out.println("获取此集合元素的个数:" + set.size());
        
        set.remove(3);
        
        //遍历 : foreach
        for (Integer integer : set) {
            System.out.println(integer);
        }
        
        System.out.println("-------------------");
        
        //遍历:迭代器
        Iterator<Integer> it = set.iterator();
        while (it.hasNext()) {
            Integer integer = (Integer) it.next();
            System.out.println(integer);
        }
    }
}
TreeSet常用方法及Integer类型排序:数字升序

TreeSet存入String类型排序:字典排序

public class Test02 {
    
    public static void main(String[] args) {
        
        /**
         * TreeSet存入String类型排序规则是:字典排序
         */
        
        TreeSet<String> set = new TreeSet<>();
        
        set.add("c");
        set.add("a");
        set.add("cd");
        set.add("dd");
        set.add("dd");
        
        for (String string : set) {
            
            System.out.println(string);
        }
        
        
    }

}
TreeSet存入String类型排序:字典排序

实现Comparable接口的排序

public class Student implements Comparable<Student>{
    
    private String name;
    private int age;
    private char sex;
    private String classId;
    private String id;
    
    @Override
    public int compareTo(Student o) {//排序规则:按年龄排序
        
//        if(this.age > o.age){
//            return 1;
//        }else if(this.age < o.age){
//            return -1;
//        }else{
//            return 0;
//        }
        
        return this.age - o.age;
    }
    
    public Student() {
    }

    public Student(String name, int age, char sex, String classId, String id) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.classId = classId;
        this.id = id;
    }

    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 char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public String getClassId() {
        return classId;
    }

    public void setClassId(String classId) {
        this.classId = classId;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((classId == null) ? 0 : classId.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (classId == null) {
            if (other.classId != null)
                return false;
        } else if (!classId.equals(other.classId))
            return false;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", classId=" + classId + ", id=" + id + "]";
    }

}
实现Comparable接口的排序
public class Test03 {
    
    public static void main(String[] args) {
        
        TreeSet<Student> set = new TreeSet<>();
        
        set.add(new Student("麻生希", 27, '女', "1807", "001"));
        set.add(new Student("小西满里惠", 27, '女', "1807", "002"));
        set.add(new Student("泷泽萝拉", 23, '女', "1807", "003"));
        set.add(new Student("铃原爱蜜莉", 21, '女', "1807", "004"));
        set.add(new Student("北条麻衣", 39, '女', "1807", "005"));
        set.add(new Student("夏凡", 27, '男', "1807", "006"));
        
        for (Student stu : set) {
            System.out.println(stu);
        }
        
    }

}
Test.java

创建TreeSet时,传入Comparator的实现类的对象实现排序

public class Test04 {
    
    public static void main(String[] args) {
        
        TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {//重新编写排序规则:按照名字长度排序,长度一致按年龄排序,重复学生不能存入TreeSet集合里
                
                if(o1.equals(o2)){//判断对象是否相同(判断classId和id)
                    return 0;
                }
                
                if(o1.getName().length() != o2.getName().length()){//名字长度不一致
                    return o1.getName().length() - o2.getName().length();
                }else{
                    
                    if(o1.getAge() != o2.getAge()){
                        return o1.getAge() - o2.getAge();
                    }else{
                        return 1;
                    }
                    
                }
            }
        });
        
        set.add(new Student("麻生希", 27, '女', "1807", "001"));
        set.add(new Student("小西满里惠", 27, '女', "1807", "002"));
        set.add(new Student("泷泽萝拉", 23, '女', "1807", "003"));
        set.add(new Student("铃原爱蜜莉", 21, '女', "1807", "004"));
        set.add(new Student("北条麻衣", 39, '女', "1807", "005"));
        set.add(new Student("夏凡", 27, '男', "1807", "006"));
        set.add(new Student("夏凡", 27, '男', "1807", "007"));
        
        for (Student stu : set) {
            System.out.println(stu);
        }
        
    }

}
Test.java

Map实现类之TreeMap

基本方法

public class Test01 {

    public static void main(String[] args) {

        //排序遵循了Integer的排序规则
        TreeMap<Integer, String> map = new TreeMap<>();

        map.put(27, "小西满里惠");
        map.put(23, "杨程");
        map.put(21, "铃原爱蜜莉");
        map.put(32, "北条麻衣");
        map.put(28, "夏凡");
        map.put(18, "贾玲");

        //替换
        map.put(18, "舒玲");

        //删除(通过key删除映射关系)
        map.remove(28);

        System.out.println("通过key获取到指定的值:" + map.get(18));
        System.out.println("判断此集合是否有指定key:" + map.containsKey(18));
        System.out.println("判断此集合是否有指定value:" + map.containsValue("杨程"));
        System.out.println("判断此集合中是否没有元素:" + map.isEmpty());
        System.out.println("获取此集合中映射关系的个数为:" + map.size());

        //遍历:keySet 不适用:因为二叉树的数据结构,会使得数据丢失
        Set<Integer> set = map.keySet();
        for (Integer key : set) {
            String value = map.get(key);
            System.out.println(key + " --- " + value);
        }
        System.out.println(" ------------- ");

        //遍历:entrySet
        Set<Entry<Integer,String>> entrySet = map.entrySet();
        for (Entry<Integer, String> entry : entrySet) {
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " --- " + value);
        }

    }
}
TreeMap基本方法

Comparator接口的实现类(匿名内部类)的排序规则

public class Test02 {

    public static void main(String[] args) {

        //排序遵循了Comparator接口的实现类(匿名内部类)的排序规则
        TreeMap<Integer, String> map = new TreeMap<>(new Comparator<Integer>() {

            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });

        map.put(27, "小西满里惠");
        map.put(23, "杨程");
        map.put(21, "铃原爱蜜莉");
        map.put(32, "北条麻衣");
        map.put(28, "夏凡");
        map.put(18, "贾玲");

        //替换
        map.put(18, "舒玲");

        //删除(通过key删除映射关系)
        map.remove(28);

        System.out.println("通过key获取到指定的值:" + map.get(18));
        System.out.println("判断此集合是否有指定key:" + map.containsKey(18));
        System.out.println("判断此集合是否有指定value:" + map.containsValue("杨程"));
        System.out.println("判断此集合中是否没有元素:" + map.isEmpty());
        System.out.println("获取此集合中映射关系的个数为:" + map.size());

        //遍历:keySet 不适用:因为二叉树的数据结构,会使得数据丢失
        Set<Integer> set = map.keySet();
        for (Integer key : set) {
            String value = map.get(key);
            System.out.println(key + " --- " + value);
        }
        System.out.println(" ------------- ");

        //遍历:entrySet
        Set<Entry<Integer,String>> entrySet = map.entrySet();
        for (Entry<Integer, String> entry : entrySet) {
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " --- " + value);
        }

    }
}
Comparator接口的实现类(匿名内部类)的排序规则

集合总结

学习路线:基本使用 -> 做实验 -> 画图 -> 分析底层源码

集合:数据的容器(类似于数组)

1.Collection --- 集合(接口)

    List -- 接口(添加了对于下标进行操作的方法)
    特点:有序,且可重复的
    
        ArrayList:
            数据结构:一维数组
            应用场景:存储数据
            
        LinkedList:
            数据结构:双向链表
            应用场景:存储数据、队列模式、栈模式
            
        Vector:
            数据结构:一维数组
            
        Stack:(继承Vector)
            数据结构:一维数组
            特点:栈的数据结构
     
    Set -- 接口
    特点:无序,且不可重复
    
        HashSet:
            数据结构:Hash数组
            应用场景:元素去重
            
        TreeSet:
            数据结构:二叉树
            应用场景:自然排序
            ps:TreeSet存入元素是存到TreeMap集合中key的位置


2.Map --- 集合(接口)
    特点:键值对存储 K-V
    
        HashMap:
            数据结构:Hash数组
            特点:key是唯一的,value可以重复
        HashTable:
            数据结构:Hash数组
        ConcurrentHashMap:
            数据结构:Segment数组
            特点:分段式加锁
            
        TreeMap:
            数据结构:二叉树
            应用场景:自然排序(对key进行排序)
            

注意:
    1.理解无序: 
        无序是指:存入元素的顺序与取出元素的顺序不一致,无序不代表随机
        
    2.Collection 与 Map的区别?
        Collection存储单个元素
        Map存储两个元素    
        
    3.ArrayList vs LinkedList(两个集合的使用方法一模一样)
        区别:
            1.队列模式或栈模式就用LinkedList
            2.效率:
                添加:一样快
                插入:LinkedList快
                删除:LinkedList快
                查询:ArrayList快
            ps:平时如果不用到队列模式或栈模式就用ArrayList,因为项目中往往查询比其他功能用的频繁
    
    4.Vector vs ArrayList
        数据结构都是一维数组,但Vector-线程安全 ,ArrayList-线程不安全的
    
    5.HashMap vs Hashtable vs ComcurrenHashMap
    (使用方式一模一样)
    区别:
        1.HashMap可以存放null值,其他两个集合不可以存放null值
        2.HashMap线程不安全
          Hashtable线程安全
          ComcurrenHashMap线程安全
    
    6.Hashtable vs ComcurrenHashMap
        Hashtable:方法里加锁
        ComcurrenHashMap:Segment对象中加锁,又叫做分段式加锁
        ps:分段式加锁要比方法里加锁的效率更好
    
    7.TreeSet特点是排序,请问排序规则的代码是写在哪个地方的??
        TreeSet --- Integer : 数字升序
        TreeSet --- String    : 字典排序
        答:排序规则写在存入元素所属类里
    
    8.Comparable、Comparator排序接口
        Comparable排序接口:一个类的对象要存入TreeSet里,这个对象所属类就必须实现此接口里的compareTo排序方法
         
        Comparator排序接口:元素所属的类是别人提供的,又想改变排序规则,就在创建TreeSet时,传入Comparator的实现类的对象(一般使用匿名内部类)
        调用的优先级别:Comparator > Comparable
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
集合总结

 

 

posted @ 2018-11-01 14:59  cmlx  阅读(221)  评论(0)    收藏  举报