zoukankan      html  css  js  c++  java
  • 18_集合

    一. 集合

    • 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能

    • 和数组区别

      • 数组长度固定,集合长度不固定
      • 数组可以存储基本类型和引用类型,集合只能存储引用类型
    • 位置:java.util.*;

    Collection体系集合

    Interface Collection
    Interface List Interface Set
    Class ArrayList Class LinkedList Class Vector Class HashSet Interface SortedSet
    Class TreeSet
    • 该体系结构的根接口,代表一组对象,称为集合
    • List接口的特点
      • 有序、有下标、元素可重复
    • Set接口的特点
      • 无序、无下标、元素不能重复

    1. Collection接口

    特点:代表一组任意类型的对象,无序、无下标、不能重复

    方法:

            boolean add(Object obj)//1. 添加一个对象
            boolean addAll(Collection c)//2. 将一个集合中的所有对象添加到此集合中
            void clear()//3. 清空此集合中的所有对象
            boolean contains(Object o)//4. 检查此集合中是否包含o对象
            boolean equals(Object o)//5. 比较此集合是否与指定对象相等
            boolean isEmpty()//6. 判断此集合是否为空
            boolean remove(Object o)//7. 在此集合中移除o对象
            int size()//8. 返回此集合中元素的个数
            Object[] toArray()//9. 将此集合转换成数组
            
        
    
    	//创建集合
            Collection collection = new ArrayList();
            //1. 添加元素
            collection.add("苹果");
            collection.add("西瓜");
            collection.add("香蕉");
            System.out.println("元素个数:" + collection.size());
            System.out.println(collection);
    
    //        //2. 删除元素
    //        collection.remove("西瓜");
    //        collection.clear();
    //        System.out.println("元素个数:" + collection.size());
    
            //3. 遍历元素(重点)
            //3.1 使用增强for
            for (Object object : collection) {
                System.out.println(object);
            }
            //3.2 使用迭代器(专门用来遍历集合的一种方式)
            //hasNext()有没有下一个元素
            //next()获取下一个元素
            //remove()删除当前元素
            System.out.println("----------");
            Iterator iter = collection.iterator();
            while (iter.hasNext()){
                String s = (String)iter.next();
                System.out.println(s);
                //迭代过程中无法使用collection的remove()方法
                //iter.remove();
            }
            System.out.println("元素个数:" + collection.size());
            //4. 判断
            System.out.println(collection.contains("西瓜"));
            System.out.println(collection.isEmpty());
    

    2. List接口与实现类

    List接口

    特点:有序、有下标、元素可以重复

    方法:

    	void add(int index, Object o)//1. 在index位置插入对象o
            boolean addAll(int index, Collection c)//2. 将一个集合中的元素添加到此集合中的index位置
            Object get(int index)//3. 返回集合中指定位置的元素
            List subList(int fromIndex, int toIndex)//4. 返回fromIndex和toIndex之间的集合元素
    
    	//1. 添加元素
            List list = new ArrayList();
            list.add("手机");
            list.add("耳机");
            list.add(0,"电脑");//将电脑放在下标为0 的位置
            System.out.println("元素个数:" + list.size());
            System.out.println(list.toString());//电脑 手机
            //2. 删除元素
            list.remove("耳机");
            System.out.println("删除后的元素个数:" + list.size());
            System.out.println(list.toString());
            //3. 遍历
            //3.1 使用for遍历
            System.out.println("----------3.1使用for遍历--------");
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i));
            }
            //3.2 使用增强for
            System.out.println("----------3.2使用增强for--------");
            for (Object o : list) {
                System.out.println(o);
            }
            //3.3 使用迭代器iterator
            System.out.println("----------3.3使用迭代器iterator--------");
            Iterator iter = list.iterator();
            while (iter.hasNext()){
                System.out.println(iter.next());
            }
            //3.4 使用列表迭代器listIterator,可以向前,向后遍历,添加修改删除元素
            System.out.println("----------3.4使用列表迭代器listIterator从前往后--------");
            ListIterator listIterator = list.listIterator();
            while (listIterator.hasNext()){
                //0:电脑
                //1:手机
                System.out.println(listIterator.nextIndex() + ":" + listIterator.next());
            }
            System.out.println("----------3.4使用列表迭代器listIterator从后往前--------");
            while (listIterator.hasPrevious()){
                //1:手机
                //0:电脑
                System.out.println(listIterator.previousIndex() + ":" + listIterator.previous());
            }
            //4. 判断
            System.out.println(list.contains("电脑"));
            System.out.println(list.isEmpty());
            //5. 获取位置
            System.out.println(list.indexOf("电脑"));
    		//6.subList返回子集合,含头不含尾
            List sublist = list.subList(0,1);
            System.out.println(sublist.toString());//[电脑]
    

    List实现类

    (1) ArrayList

    ArrayList【重点】:

    • 数组结构实现,查询快、增删慢
    • JDK1.2版本,运行效率快、线程不安全
    • 源码分析:
      • 默认容量 DEFAULT_CAPACITY = 10;(还未向集合中添加任何元素时,容量为0,添加任意元素后,容量为10,每次扩容为原来的1.5倍)
      • 存放元素的数组 elementData
      • 实际元素个数 size
    	//创建集合 ArrayList
            ArrayList arrayList = new ArrayList();
            //1. 添加元素
            Student s1 = new Student("张三", 18);
            Student s2 = new Student("李四", 19);
            Student s3 = new Student("王五", 20);
    
            arrayList.add(s1);
            arrayList.add(s2);
            arrayList.add(s3);
            System.out.println("元素个数:" + arrayList.size());
            System.out.println(arrayList.toString());
    //        //2. 删除元素
    //        arrayList.remove(0);//删除下标为0的s1
    //        arrayList.remove(s2);//删除s2
    //        System.out.println(arrayList.toString());
    //
    //        arrayList.remove(new Student("王五",20));//equals(this == obj)
    //        System.out.println(arrayList.size());
    
            //3. 遍历元素【重点】
            //3.1 使用迭代器
            System.out.println("-------3.1 使用迭代器-------");
            Iterator iter = arrayList.iterator();
            while (iter.hasNext()){
                Student s = (Student)iter.next();
                System.out.println(s.toString());
            }
            //3.2 使用列表迭代器
            System.out.println("-------3.2 使用列表迭代器正序-------");
            ListIterator lit = arrayList.listIterator();
            while (lit.hasNext()){
                Student s = (Student)lit.next();
                System.out.println(s.toString());
            }
            //3.2 使用列表迭代器
            System.out.println("-------3.2 使用列表迭代器逆序-------");
            while (lit.hasPrevious()){
                Student s = (Student) lit.previous();
                System.out.println(s.toString());
            }
            //4. 判断
            System.out.println(arrayList.contains(s1));
            System.out.println(arrayList.isEmpty());
    
            //5. 查找
            System.out.println(arrayList.indexOf(s2));
    		
    		
    		
    

    (2) Vector

    • Vector:
      • 数组结构实现,查询快、增删慢
      • JDK1.0版本,运行效率慢、线程安全
    	//创建集合 Vector
            Vector vector = new Vector();
            vector.add("苹果");
            vector.add("香蕉");
            vector.add("橘子");
            //Vector用法与ArrayList基本一致,但遍历时,ArrayList用的是列表迭代器,Vector则是是枚举方法Enumeration
            Enumeration enumeration = vector.elements();
            while (enumeration.hasMoreElements()){
                String s = (String)enumeration.nextElement();
                System.out.println(s);
            }
    

    (3) LinkedList

    • LinkedList :
      • 链表结构实现,查询慢、增删快
      • 用法与ArrayList基本一致

    3. 泛型和工具类

    • java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型、把类型作为参数传递,类型安全的集合、强制集合元素的类型必须一致
    • 常见形式有泛型类、泛型接口、泛型方法
    • 语法:<T,...> T称为类型占位符,表示一种引用类型
    • 好处:
      • 提高代码的复用性
      • 编译时即可检查,而非运行时抛出异常
      • 访问时,不必类型转换(拆箱),防止类型转换异常,提高代码的安全性
    • 注意:不同泛型之间引用不能相互赋值,泛型不存在多态

    (1)泛型类

    public class MyGeneric<T> {
    
        //使用泛型T,T表示类型占位符,表示一种引用类型,如使用多个用逗号隔开
        //创建变量
        T t;
    
        //2. 泛型作为方法的参数
        public void show(T t){
            System.out.println(t);
        }
    
        //3. 泛型作为方法的返回值
        public T getT(){
    
            return t;
        }
    }
    

    (2)泛型接口

    //注意:不能泛型静态常量
    public interface MyInterface<T> {
        String name = "张三";
    
        T server(T t);
    }
    

    泛型接口的实现类写法一(泛型接口的类型确定)

    public class MyInterfaceIMPL implements MyInterface<String> {
    
        @Override
        public String server(String t) {
            System.out.println(t);
            return t;
        }
    }
    

    泛型接口的实现类写法二(泛型接口的类型不确定,泛型类的类型也不确定)

    public class MyInterfaceIMPL2<T> implements MyInterface<T>{
    
        @Override
        public T server(T t) {
            System.out.println(t);
            return t;
        }
    }
    

    (3)泛型方法

    (语法: 返回值类型)

    public class MyGenericMethod {
    
        //泛型方法
        public <T> T show(T t){
            System.out.println("泛型方法");
            System.out.println(t);
            return t;
        }
    }
    

    代码运行测试

    public class TestGeneric {
    
        public static void main(String[] args) {
    
            //使用泛型类创造对象
            //1. 泛型只能使用引用类型 2. 不同泛型类型对象之间不能相互赋值
            MyGeneric<String> myGeneric = new MyGeneric<String>() ;
            myGeneric.show("大家好,加油!");//大家好,加油!
            myGeneric.t = "hello";
            String string = myGeneric.getT();
            System.out.println(string);//hello
    
            MyGeneric<Integer> myGeneric1 = new MyGeneric<Integer>();
            myGeneric1.show(123);
            myGeneric1.t = 456;
            Integer integer = myGeneric1.getT();
            System.out.println(integer);
    
            //泛型接口的使用
            MyInterfaceIMPL impl = new MyInterfaceIMPL();
            System.out.println(impl.name);
            impl.server("aaa");
    
    
    //        MyInterface<String> im = new MyInterfaceIMPL();
    //        System.out.println(im.name);
    //        im.server("sss");
    
            MyInterfaceIMPL2<Integer> impl2 = new MyInterfaceIMPL2<Integer>();
            impl2.server(111);
    
            //泛型方法
            MyGenericMethod method = new MyGenericMethod();
            method.show("s");
            method.show(123);
        }
    }
    

    4. Set接口与实现类

    • 特点:无序、无下标、元素不可重复
    • 方法:全部继承自Collection中的方法

    Set接口

    	//创建集合
            Set<String> set = new HashSet<>();
            //1. 添加数据
            set.add("小米");
            set.add("大米");
            set.add("黑米");
            set.add("糙米");
            //set.add("黑米");
            System.out.println("元素个数:" + set.size());
            System.out.println(set.toString());
            //2. 删除数据
            set.remove("黑米");
            System.out.println(set.toString());
            //3. 遍历(重点)
            //3.1 增强for
            for (String s : set) {
                System.out.println(s);
            }
            //3.2 迭代器
            Iterator<String> iter = set.iterator();
            while (iter.hasNext()){
                String s = iter.next();
                System.out.println(s);
            }
            //4. 判断
            System.out.println(set.contains("大米"));
            System.out.println(set.isEmpty());
    

    (1)HashSet

    • 基于HashCode计算元素存放位置
    • 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
    	//创建集合
            HashSet<Person> person = new HashSet<>();
            //1. 添加数据
            Person s1 = new Person("唐三", 18);
            Person s2 = new Person("小舞", 18);
            Person s3 = new Person("唐昊", 38);
    
            person.add(s1);
            person.add(s2);
            person.add(s3);
            person.add(new Person("唐三", 18));//因为重写了HashCode和equals方法,所以未能添加成功
            System.out.println("学生个数" + person.size());
            System.out.println(person.toString());
            //2. 删除数据
            person.remove(s3);
            System.out.println("学生个数" + person.size());
            //3. 遍历数据
            //3.1 增强for
            for (Person person1 : person) {
                System.out.println(person1);
            }
            //3.2 迭代器
            Iterator<Person> iter = person.iterator();
            while (iter.hasNext()){
                Person person1 = iter.next();
                System.out.println(person1);
            }
    
            //4. 判断
            //因为重写了HashCode和equals方法,所以返回true
            System.out.println(person.contains(new Person("唐三", 18)));//true
    

    重写了hashcode和的equals方法

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Person person = (Person) o;
            return age == person.age &&
                    Objects.equals(name, person.name);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    

    (2)TreeSet

    • 基于排列顺序实现元素不重复
    • 实现了SortedSet接口,对集合元素自动排序
    • 元素对象的类型必须实现Comparable接口,指定排序规则
    • 通过CompareTo方法确定是否为重复元素
    	//要求:元素必须实现Comparable接口,CompareTo方法的返回值为0,认为是重复元素		
    	//创建集合
            TreeSet<Person> person = new TreeSet<>();
            //1. 添加元素
            Person s1 = new Person("张三", 18);
            Person s2 = new Person("李四", 19);
            Person s3 = new Person("王五", 20);
            Person s4 = new Person("王五", 25);
            person.add(s1);
            person.add(s2);
            person.add(s3);
            person.add(s4);
    
            System.out.println("元素个数:" + person.size());
            System.out.println(person.toString());
            //2. 删除
            person.remove(new Person("王五", 25));
            System.out.println(person.toString());
            //3. 遍历
            //3.1 增强for
            for (Person person1 : person) {
                System.out.println(person1);
            }
            //3.2 迭代器
            Iterator<Person> iter = person.iterator();
            while (iter.hasNext()){
                Person p = iter.next();
                System.out.println(p);
            }
            //4. 判断
            System.out.println(person.contains(s1));
            System.out.println(person.contains(new Person("王五", 25)));
            System.out.println(person.isEmpty());
    

    Person类实现了Comparable接口

            //先按姓名比,再按年龄比
            @Override
            public int compareTo(Person o) {
                int n1 = this.getName().compareTo(o.getName());
                int n2 = this.getAge()-o.getAge();
    
                return n1==0?n2:n1;
            }
    

    使用TreeSet集合实现字符串按照长度进行排序

    package com.collection.Set;
    
    import java.util.Comparator;
    import java.util.TreeSet;
    
    /**
     * 
     * @description: 使用TreeSet集合实现字符串按照长度进行排序
     */
    
    public class Demo06 {
    
        public static void main(String[] args) {
    
            TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    int i1 = o1.length()-o2.length();
                    int i2 = o1.compareTo(o2);
    
                    return i1==0?i2:i1;
                }
            });
            treeSet.add("zhangsan");
            treeSet.add("lisi");
            treeSet.add("wangwu");
            treeSet.add("liuliu");
            treeSet.add("beijing");
            treeSet.add("shanghai");
            System.out.println(treeSet.toString());
        }
    }
    
    

    5. Map接口与实现类

    Map接口

    特点:

    • 用于存储任意键值对(Key-Value)
    • 键:无序、无下标、不允许重复(唯一)
    • 值:无序、无下标、允许重复
    Interface Map
    Class HashMap Interface SortedMap
    Class TreeMap

    方法:

    	V put(K key,V value)//将对象存入到集合中,关联键值。Key重复则覆盖原值
    	Object get(Object key)//根据键获取对应的值
    	Set<K>//返回所有Key
    	Collection<V> values()//返回包含所有值的Collecton集合
    	Set<Map.Entry<K,V>>//键值匹配的Set集合
    
    	//创建Map集合
            Map<String, String> map = new HashMap<>();
            //1. 添加元素
            map.put("cn", "中国");
            map.put("usa", "美国");
            map.put("ck", "英国");
            //map.put("ck", "yingguo");//会给cn重新赋值
            System.out.println("元素个数:" + map.size());
            System.out.println(map.toString());
    
            //2. 删除
            map.remove("usa");
            System.out.println(map.size());
    
            //3. 遍历
            //3.1 使用keySet()方法
            System.out.println("-------使用keySet()方法-----------");
            Set<String> keys = map.keySet();
            for (String key : keys) {
                System.out.println(key + map.get(key));
            }
            //3.2 使用entrySet()方法
            System.out.println("-------使用entrySet()方法-----------");
            Set<Map.Entry<String, String>> entries = map.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                System.out.println(entry.getKey() + entry.getValue());
            }
    
            //4. 判断
            System.out.println(map.containsKey("cn"));
            System.out.println(map.containsValue("中国"));
    

    (1)HashMap

    • HashMap【重点】
      • JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value
    	//创建集合
    	//刚创建HashMap还没有添加元素时,table=null size=0 目的:节省空间
            HashMap<Teacher, String> teacher = new HashMap<Teacher, String>();
            //1. 添加元素
            Teacher s1 = new Teacher("唐三", 18);
            Teacher s2 = new Teacher("小舞", 19);
            Teacher s3 = new Teacher("小奥", 20);
    
            teacher.put(s1, "北京");
            teacher.put(s2, "上海");
            teacher.put(s3, "广州");
            teacher.put(new Teacher("唐三", 18), "西安");//因为重写了HashCode和equals方法,所以未能添加
            System.out.println("元素个数" + teacher.size());
            System.out.println(teacher.toString());
            //2. 删除数据
            teacher.remove(s3);
            System.out.println("学生个数" + teacher.size());
            //3. 遍历数据
            //3.1 keySet
            Set<Teacher> keys = teacher.keySet();
            for (Teacher key : keys) {
                System.out.println(key + teacher.get(key));
            }
            //3.2 entrySet
            Set<Map.Entry<Teacher, String>> entries = teacher.entrySet();
            for (Map.Entry<Teacher, String> entry : entries) {
                System.out.println(entry.getKey() + entry.getValue());
            }
    
            //4. 判断
            //因为重写了HashCode和equals方法,所以返回true
            System.out.println(teacher.containsKey(s1));//true
            System.out.println(teacher.containsKey(new Teacher("小奥", 20)));//true
    
    

    源码总结:

    1. HashMap 刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16
    2. 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
    3. jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
    4. jdk1.8 当链表长度小于6时,调整成链表
    5. jdk1.8以前,链表是头插入,jdk1.8以后是尾插入

    Hashtable:

    jdk1.0版本,线程安全,运行效率慢;不允许null作为key或是value

    Properties:

    Hashtable的子类,要求Key和value 都是String。通常用于配置文件的读取

    (2)TreeMap

    • 实现了SortedMap接口(Map的子接口),可以对Key自动排序
    	//要求:元素必须实现Comparable接口,CompareTo方法的返回值为0,认为是重复元素		
    	TreeMap<Teacher, String> treeMap = new TreeMap<>();
            //1. 添加元素
            Teacher s1 = new Teacher("唐三", 21);
            Teacher s2 = new Teacher("小舞", 23);
            Teacher s3 = new Teacher("小奥", 20);
    
            treeMap.put(s1, "aaa");
            treeMap.put(s2, "bbb");
            treeMap.put(s3, "ccc");
            treeMap.put(new Teacher("小奥",20), "ddd");
            System.out.println("元素个数:" + treeMap.size());
            System.out.println(treeMap.toString());
    
            //2.删除
            treeMap.remove(new Teacher("小奥",20));
            System.out.println("元素个数:" + treeMap.size());
    
            //3. 遍历
            //3.1 使用keySet
            Set<Teacher> keys = treeMap.keySet();
            for (Teacher key : keys) {
                System.out.println(key + "-----" + treeMap.get(key));
            }
            //3.2 使用entrySet
            Set<Map.Entry<Teacher, String>> entries = treeMap.entrySet();
            for (Map.Entry<Teacher, String> entry : entries) {
                System.out.println(entry.getKey() + "-----" + entry.getValue());
            }
            //判断
            System.out.println(treeMap.containsKey(new Teacher("小舞", 23)));
    

    6.Collections工具类

    概念:集合工具类,定义了除了存取以外的集合常用方法

    方法:

    	public static void reverse(List<?> list)//反转集合中元素的顺序
            public static void shuffle(List<?> list)//随机重置集合元素的顺序
            public static void sort(List<T> list)//升序排序(元素类型必须实现Comparable接口)
                
    
    	List<Integer> list = new ArrayList<>();
            list.add(8);
            list.add(5);
            list.add(6);
    
            //sort排序
            System.out.println("排序前:" + list.toString());//[8, 5, 6]
            Collections.sort(list);
            System.out.println("排序后:" + list.toString());//[5, 6, 8]
            //binarySearch二分查找
            int i = Collections.binarySearch(list, 6);
            System.out.println(i);//1
    
            //copy复制,现集合长度需要和被复制集合长度一致
            List<Integer> dest = new ArrayList<>();
    
            for (int j = 0; j < list.size(); j++) {
                dest.add(0);
            }
            Collections.copy(dest, list);
            System.out.println(dest.toString());//[5, 6, 8]
    
            //reverse反转
            Collections.reverse(list);
            System.out.println("反转后:" + list.toString());//[8, 5, 6]
    
            //shuffle 打乱
            Collections.shuffle(list);
            System.out.println("打乱后:" + list.toString());//[5, 8, 6] 随机排序
    
            //补充:list转数组
            Integer[] arr = list.toArray(new Integer[5]);
            System.out.println(arr.length);
            System.out.println(Arrays.toString(arr));
    
            //数组转集合
            String[] names = new String[]{"aa","bb","cc"};
            //此时的集合是受限集合,不能添加和删除
            List<String> list2 = Arrays.asList(names);
            System.out.println(list2);
    
            //基本类型数组转成集合时,需要修改为包装类
            Integer[] nums = {10, 20, 30};
            List<Integer> list3 = Arrays.asList(nums);
            System.out.println(list3);
    

    二. 集合总结

    • 集合的概念
      • 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法
    • List集合
      • 有序、有下标、元素可以重复。(ArrayList、LinkList、Vector)
    • Set集合
      • 无序、无下标、元素不可重复。(HashSet,TreeSet)
    • Map集合
      • 存储一对数据,无序、无下标、键不可重复,值可重复、(HashMap、HashTable、TreeMap)
    • Collections
      • 集合工具类,定义了除存取以外的集合常用方法
  • 相关阅读:
    【数论】X problem
    【数论】约瑟夫问题
    【组合数学】购票问题
    【组合数学】计数原理
    spring batch批处理框架学习
    eclipse自动添加javadoc注释
    eclipse手动安装alibaba代码规范插件
    现代支付系统的资金流向
    利用网易有道在谷歌浏览器进行网页滑词翻译
    spring配置遇到的问题
  • 原文地址:https://www.cnblogs.com/MRASdoubleZ/p/14459896.html
Copyright © 2011-2022 走看看