Java集合的用法及特点

2020-05-16  本文已影响0人  魏皇子

单列LIst集合

单列列表集合:

副本和集合的区别:

区别1:

#数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值  
集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但在存储的时候会自动装箱变成对象

区别2:

分布长度是固定的,不能自动增长*集合的长度的是可变的,可以根据元素的增加而增长1 2 3 C:复制和集合什么时候用

数组和集合什么时候用:

  1. 如果元素个数是固定的推荐用堆叠

  2. 如果元素个数不是固定的推荐用集合

Collection集合的基本功能用法

public static void main(String[] args) {
    Collection c = new ArrayList();    //创建集合对象
    c.add("a");       //添加元素,返回值为boolean
    c.remove("a");    //删除元素,返回值为boolean
    c.clear();        //清空集合,无返回值
    boolean pd = c.contains("a");   //判断是否包含元素,包含则返回true
    boolean pd = c.isEmpty();        //判断集合是否为空,为空返回true
    int num = c.size();            //获取集合中元素的个数,返回值为int
}

Collection集合的带All功能用法

public static void main(String[] args) {
    Collection c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("c");
    c1.add("d");

    Collection c2 = new ArrayList();
    c2.addAll(c1);      //c1全部赋值给c2集合
    c1.removeAll(c2);   //删除c1内与c2交集的部分,返回值为boolean
    boolean b = c1.containsAll(c2);//判断调用的集合是否包含传入的集合
    boolean c = c1.retainAll(c2);//取c1和c2的交集,存入c1
    //如果调用的集合改变就返回true,注意:如果c2无值则c1也将变为无值
    System.out.println(c1);
    System.out.println(c2);
}

集合的遍历之集合转数组遍历

public static void main(String[] args) {
    Collection c = new ArrayList();    //创建集合对象
    c.add("a");       
    c.add("b");    
    c.add(new Student("王欢", 28));    //创建对象存入数组
   
    Object[] arr = c.toArray();     //将集合转换为数组
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
    
}

集合的遍历之迭代器遍历

public static void main(String[] args) {
    Collection c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("c");
    c1.add("d");

    Iterator it = c1.iterator();//获取c1集合的迭代器
    while (it.hasNext()) {  //判断集合中是否有元素
        System.out.println(it.next());  //获取元素
    }

    Collection c2 = new ArrayList();
    c2.add(new Student("张三", 23));
    c2.add(new Student("李四", 18));

    Iterator it2 = c2.iterator();//获取c2集合的迭代器
    while (it2.hasNext()) {
        Student s = (Student)it2.next();    //向下转型
        System.out.println(s.getName());
    }

}

List集合的特有功能

public static void main(String[] args) {
    List c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("c");
    c1.add("d");

    c1.add(1, "e");//指定索引位置添加元素
    Object obj = c1.remove(1);//通过索引删除元素并返回删除的元素
    Object obj2 = c1.get(0);    //通过索引获取指定元素
    c1.set(0, "z");         //将指定位置的元素修改
    System.out.println(obj2);
    System.out.println(c1);

}

List集合特有迭代器

该迭代器可以在遍历的同时向集合内添加元素

public static void main(String[] args) {
    List c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("nan");
    c1.add("c");
    c1.add("d");

    ListIterator it = c1.listIterator();//List集合特有迭代器
    while (it.hasNext()) {
        String str = (String) it.next();
        if ("nan".equals(str)) {    //当集合中存在nan时则添加元素
            it.add("zzzzzzz");      //通过迭代器添加元素
        }
    }
    System.out.println(c1);

}

Vector的特有功能概述和测试【注意:Vector已被完全替代,请勿再使用】

public static void main(String[] args) {
    Vector v = new Vector();
    v.addElement("a");
    v.addElement("b");
    v.addElement("c");
    v.addElement("d");

    Enumeration en = v.elements();//获取枚举
    while (en.hasMoreElements()) {//判断集合中是否有元素
        System.out.println(en.nextElement());//获取集合中的元素
    }
}

List的三个子类的特点

ArrayList:


底层数据结构是数组,查询快,增删慢。

线程不安全,效率高。

Vector:

底层数据结构是数组,查询快,增删慢。

线程安全,效率低。

Vector相对ArrayList查询慢(线程安全的)

Vector相对LinkedList增删慢(数组结构)

LinkedList:

底层数据结构是链表,查询慢,增删快。

线程不安全,效率高。

Vector和ArrayList的区别

Vector是线程安全的,效率低

ArrayList是线程不安全的,效率高

共同点:都是数组实现的

ArrayList和LinkedList的区别

ArrayList底层是数组结果,查询和修改快

LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢

共同点:都是线程不安全的

注意:线程不安全可以通过工具类改为安全的


如何选择:

查询多用ArrayList

增删多用LinkedList

如果都多ArrayList

#### 案例:ArrayList去除集合中字符串的重复值
```java
public class CeShi {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.add("a");
        list.add("b");
        list.add("b");

        ArrayList abc = JiHeFF(list);
        System.out.println(abc);
    }

    public static ArrayList JiHeFF(ArrayList list) {
        ArrayList newList = new ArrayList();    //创建一个新集合
        Iterator it = list.iterator();          //获取迭代器

        while (it.hasNext()) {        //判断老集合中是否有元素,遍历老集合
            Object obj = it.next();  //将每一个元素临时记录住
            if (!newList.contains(obj)) {   //如果新集合中不包含该元素
                newList.add(obj);       //将该元素添加到新集合中
            }
        }
        return newList;     //将新集合返回
    }
}

案例:ArrayList去除集合重复自定义对象元素

注意:需要重写类的equals()方法

public class CeShi {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Student("张三", 23));
        list.add(new Student("张三", 23));
        list.add(new Student("李四", 23));
        list.add(new Student("李四", 23));
        list.add(new Student("李四", 23));

        ArrayList newList = JiHeFF(list);
        System.out.println(newList);
    }

    public static ArrayList JiHeFF(ArrayList list) {
        ArrayList newList = new ArrayList();    //创建一个新集合
        Iterator it = list.iterator();          //获取迭代器

        while (it.hasNext()) {        //判断老集合中是否有元素,遍历老集合
            Object obj = it.next();  //将每一个元素临时记录住
            if (!newList.contains(obj)) {   //如果新集合中不包含该元素
                newList.add(obj);       //将该元素添加到新集合中
            }
        }
        return newList;     //将新集合返回
    }
}

//重写Student类的equals()方法,可以通过IDEA快速生成
@Override
public boolean equals(Object o) {
    Student s = (Student) o;
    return this.name.equals(s.name) && this.age == s.age;
}

案例:ArrayList通过迭代器获取自定义对象指定属性值

public static void main(String[] args) {
    ArrayList<Person> list = new ArrayList<Person>();
    list.add(new Person("张三", 23));
    list.add(new Person("李四", 24));
        
    Iterator<Person> it = list.iterator();    //获取迭代器
    while(it.hasNext()) {
        //System.out.println(it.next().getName() + "..." + it.next().getAge());//next方法只能调用一次,如果调用多次会将指针向后移动多次
        Person p = it.next();    //声明对象并将数据存入           
        System.out.println(p.getName() + "..." + p.getAge());    //打印所需要的属性
    }
}

LinkedList的特有功能

public static void main(String[] args) {
        LinkedList list = new LinkedList();
        list.addFirst("a"); //往头添加元素
        list.addFirst("b");
        list.addFirst("c");
        list.addFirst("d");
        list.addLast("e");  //往尾添加元素
        
        //System.out.println(list.getFirst());//获取第一个
        //System.out.println(list.getLast());//获取最后一个
        //System.out.println(list.removeFirst());//删除第一个
        //System.out.println(list.removeLast());//删除最后一个
        
        System.out.println(list.get(1));//获取索引位置的元素,其实并不是靠索引,因为是链表结构,靠的是挨个查询
        System.out.println(list);
    }

增强for的功能概述和测试(foreach)

简化遍历

增强for循环底层依赖的是迭代器(Iterator)

//增强for功能演示
public class CeShi {
    public static void main(String[] args) {
        ArrayList<Student> list1 = new ArrayList<>();
        list1.add(new Student("张三", 23));
        list1.add(new Student("张三", 23));
        list1.add(new Student("李四", 23));
        list1.add(new Student("李四", 23));
        list1.add(new Student("李四", 23));
        for (Student i : list1) {
            Student s1 = i;
            System.out.println(i.getName());
        }
        System.out.println("==============================");
        int[] arr = {11, 22, 33, 44, 55};
        for (int i : arr) {
            System.out.println(i);
        }
    }
}

集合元素的三种删除方式测试

增强for循环不能删除

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("b");
    list.add("c");
    list.add("d");
        
    //1,普通for循环删除,索引要--
    /*for(int i = 0; i < list.size(); i++) {
        if("b".equals(list.get(i))) {
            list.remove(i--);                           //通过索引删除元素
        }
    }*/
        
    //2,迭代器删除
    /*Iterator<String> it = list.iterator();
    while(it.hasNext()) {
        if("b".equals(it.next())) {
            //list.remove("b");                         //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
            it.remove();
        }
    }*/
        
    /*for(Iterator<String> it2 = list.iterator(); it2.hasNext();) {
        if("b".equals(it2.next())) {
            //list.remove("b");                         //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
            it2.remove();
        }
    }*/
    //3,增强for循环,增强for循环不能删除,只能遍历
    for (String string : list) {
        if("b".equals(string)) {
            list.remove("b");
        }
    }
    System.out.println(list);
}

单列Set集合:

//Set集合,无索引,不可以重复,无序(存取不一致)
//注意:存储类对象则需要修改类对象的equals和hashCode方法,否则可以存储重复对象
//定义HashSet
HashSet<Student> hs = new HashSet<>();
hs.add(new Student("张三", 23));

//定义LinkedHashSet,底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.add("a");

//定义TreeSet,用来对象元素进行排序,同样他也可以保证元素的唯一
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);

双列Map集合:

A:Map集合的功能概述

Map<String, Integer> map = new HashMap<>();
Integer i1 = map.put("张三", 23);//添加
Integer value = map.remove("张三");   //根据键删除元素,返回键对应的值
System.out.println(map.containsKey("张三"));      //判断是否包含传入的键
System.out.println(map.containsValue(100));     //判断是否包含传入的值

第一种迭代方式

public static void main(String[] args) {
    HashMap<String, Integer> map = new HashMap<>();
    map.put("张三", 23);
    map.put("李四", 24);
    map.put("王五", 25);
    map.put("赵六", 26);

    Integer i = map.get("张三");   //根据键获取值

    //获取所有的键
    Set<String> keySet = map.keySet();  //获取所有键的集合
    Iterator<String> it = keySet.iterator();//获取迭代器
    while (it.hasNext()) {
        String key = it.next(); //获取每一个键
        Integer value = map.get(key);//根据键获取值
        System.out.println(key + "=" + value);
    }
    System.out.println("=======================================");
    //使用增强for循环遍历
    for (String key : map.keySet()) {            //map.keySet()是所有键的集合
        System.out.println(key + "=" + map.get(key));
    }
}

第二种迭代方式

/**
     * Map集合的第二种迭代,根据键值对对象,获取键和值
     *  A:键值对对象找键和值思路:
        * 获取所有键值对对象的集合
        * 遍历键值对对象的集合,获取到每一个键值对对象
        * 根据键值对对象找键和值
     */
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三", 23);
        map.put("李四", 24);
        map.put("王五", 25);
        map.put("赵六", 26);
        
        //Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
        /*Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        //获取每一个对象
        Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
        while(it.hasNext()) {
            //获取每一个Entry对象
            Map.Entry<String, Integer> en = it.next();  //父类引用指向子类对象
            //Entry<String, Integer> en = it.next();    //直接获取的是子类对象
            String key = en.getKey();                   //根据键值对对象获取键
            Integer value = en.getValue();              //根据键值对对象获取值
            System.out.println(key + "=" + value);
        }*/
        
        for(Entry<String, Integer> en : map.entrySet()) {
            System.out.println(en.getKey() + "=" + en.getValue());
        }
    }

案例:用HashMap统计字符串中每个字符出现的次数

public class CeShi {
    public static void main(String[] args) {
        //1,定义一个需要被统计字符的字符串
        String s = "abbccddddddcccbbaa";
        //2,将字符串转换为字符数组
        char[] arr = s.toCharArray();
        //3,定义双列集合,存储字符串中字符以及字符出现的次数
        HashMap<Character, Integer> hm = new HashMap<>();
        //4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
        for (char c : arr) {
            //5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
            /*if (!hm.containsKey(c)) {//如果不包含这个键
                hm.put(c, 1);
            } else {
                hm.put(c, hm.get(c) + 1);
            } */
            hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
        }
        //6,打印双列集合获取字符出现的次数
        for (Character key : hm.keySet()) {             //hm.keySet()代表所有键的集合
            System.out.println(key + "=" + hm.get(key));//hm.get(key)根据键获取值
        }
    }
}

集合总结:

Collection(单列集合)

List(存取有序,有索引,可以重复)

    ArrayList

        底层是数组实现的,线程不安全,查找和修改快,增和删比较慢

      LinkedList

           底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢
    Vector
           底层是数组实现的,线程安全的,无论增删改查都慢

        * 如果查找和修改多,用ArrayList

        * 如果增和删多,用LinkedList

        * 如果都多,用ArrayList

 Set(存取无序,无索引,不可以重复)

    HashSet

        底层是哈希算法实现

        LinkedHashSet

            底层是链表实现,但是也是可以保证元素唯一,和HashSet原理一样
    TreeSet
            底层是二叉树算法实现

       *一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高

       * TreeSet在面试的时候比较多,问你有几种排序方式,和几种排序方式的区别

Map(双列集合)

HashMap
      底层是哈希算法,针对键

    LinkedHashMap

            底层是链表,针对键

TreeMap

      底层是二叉树算法,针对键

  *开发中用HashMap比较多
上一篇下一篇

猜你喜欢

热点阅读