zoukankan      html  css  js  c++  java
  • JavaSE笔记-集合

    Java集合大致可分为:List,Set,Map,Queue

    List:有序,可重复

    Set:无序(输出和插入顺序不一定一致),不可重复

    Map:映射关系,根据key去访问value

    Queue:队列,先进先出(FIFO)

    集合类只能存储对象

    List<int>       //错误 
    List<Integer>

    Collection体系结构

     

    圆圈表示:interface

    长方形表示:class

    带三角的实线代表继承关系,使用关键字extends

    带三角的虚线代表实现关系,使用关键字implements

    Iterable

    iterable定义了iterator(),forEach(Consumer<? super T> action)

    这2个方法用于遍历元素

    1.forEach方法遍历集合

    Consumer是一个函数式接口,只有一个accept(T t)方法,可以使用Lambda表达式

        public static void main(String[] args){
            Collection<String> coll = new HashSet<>();
            //在集合中添加10个元素
            for(int i=0;i<10;i++){
                coll.add("小王"+i);
            }
            //使用forEach遍历集合
            coll.forEach(name->System.out.println(name));
        }

     输出(因为HashSet并未实现SortedSet接口,所以里边的元素是无序的)

    2.iterator()遍历集合

     集合类使用iterator()方法,会返回一个Iterator

    Iterator接口主要用于遍历Collection中的元素

    有上边的4个方法,其中forEachRemaining()用来使用Lambda表达式来遍历集合

      2.1不使用Lambda表达式

        public static void main(String[] args){
            Collection<String> coll = new ArrayList<>();
            //在集合中添加10个元素
            for(int i=0;i<10;i++){
                coll.add("小王"+i);
            }
            //获得一个iterator
            Iterator<String> iterator = coll.iterator();
            //iterator中是否还有下一个元素
            while(iterator.hasNext()){
                //返回集合中的下一个元素
                String name = iterator.next();
                System.out.println(name);
                //删除一个元素
                if("小王5".equals(name)){
                    iterator.remove();
                }
                //更改iterator中元素,但是集合中的元素没有改变
                //因此可以得出集合传给iterator的是元素的值,而不是引用
                name = "李四";
            }
            System.out.println(coll.contains("小王5"));
        }

    注意在使用iterator迭代集合元素的过程中(不要在while循环里边改coll),不要改变集合中的元素,否则会产生ConcurrentModificationException

      2.2使用Lambda表达式

        public static void main(String[] args){
            Collection<String> coll = new ArrayList<>();
            //在集合中添加10个元素
            for(int i=0;i<10;i++){
                coll.add("小王"+i);
            }
            //获得一个iterator
            Iterator<String> iterator = coll.iterator();
            iterator.forEachRemaining(name->System.out.println(name));
        }

    3.使用foreach循环来遍历元素

        public static void main(String[] args){
            Collection<String> coll = new ArrayList<>();
            //在集合中添加10个元素
            for(int i=0;i<10;i++){
                coll.add("小王"+i);
            }
            
            for(String name:coll){
                System.out.println(name);
            }
    }

    注意在使用foreach遍历集合元素的过程中(不要在for循环里边改coll),不要改变集合中的元素,否则会产生ConcurrentModificationException

    Collection

    Collection中的操作可以操作所有的List,Set,Queue

       public static void main(String[] args){
            Collection<String> coll = new ArrayList<>();
            //在集合中添加一个元素
            coll.add("张三");
            //返回true
            System.out.println(coll.contains("张三"));
            //返回1
            System.out.println(coll.size());
            //删除元素
            coll.remove("张三");
            //返回0
            System.out.println(coll.size());
            //在集合中添加10个元素
            for(int i=0;i<10;i++){
                coll.add("小王"+i);
            }
            //把集合转换成数组
            String[] array = coll.toArray(new String[10]);
            System.out.println(array[5]);
        }

     Set

    特点是不允许包含重复元素,继承自Collection接口,没有添加额外方法

    1.HashSet

    特点

    不保证有序

    线程不安全,有2个线程同时修改HashSet时,需要通过代码同步

    集合元素可以是null

    数据结构:散列表
    HashSet判定2个元素相等的条件是:1.equals()方法比较相等  2.hashCode()返回值相等

    class A{
        @Override
        public boolean equals(Object obj) {
            return true;
        }
    }
    
    class B{
        @Override
        public int hashCode() {
            return 1;
        }
    
        @Override
        public boolean equals(Object obj) {
            return true;
        }
    }
    
    class C{
        @Override
        public int hashCode() {
            return 2;
        }
    }
    public class Test {
        public static void main(String[] args){
            Set<Object> set = new HashSet<>();
            //仅equals()相同
            set.add(new A());
            set.add(new A());
            //hashCode(),equals()均相同
            set.add(new B());
            set.add(new B());
            //仅hashCode()相同
            set.add(new C());
            set.add(new C());
            for(Object a : set){
                System.out.println(a);
            }
        }

    输出

    可以看出只有B,equals和hashCode都相同时,HashSet才会认为这2个元素使同一个元素

    当hashCode相同时,HashSet会把多个元素放在一个bucket中,构成同义词链表,会减慢访问速度

    因此,使用HashSet时,要保证2个对象equals返回true时,hashCode也要返回true

    2.TreeSet

    特点

    排过序

    线程不安全,有2个线程同时修改HashSet时,需要通过代码同步

    数据结构:红黑树

    TreeSet的排序规则

      2.1自然排序 (默认)

    调用集合元素的compareTo(Object obj)方法比较元素大小关系,然后按元素大小升序排列

    a.compareTo(b)

    a>b,返回正数

    a=b,返回0

    a<b,返回负数

    使用TreeSet时,要保证2个对象equals返回true时,a.compareTo(b)要返回0

    因此在向TreeSet中添加元素时,要实现Comparable接口,否则抛出ClassCashException

        public static void main(String[] args){
         //Integer已经实现Comparable接口 TreeSet
    <Integer> set = new TreeSet<>(); set.add(5); set.add(4); set.add(9); set.add(2); for(Integer i : set){ System.out.println(i); } }

    输出

      2.2通过Comparator接口(函数式接口)

      

    compare(a,b)

    返回正数,a>b

    返回0,a=b

    返回负数,a<b

    实现逆序,返回相反的数就行了

        public static void main(String[] args) {
         //使用TreeSet(Comparator<? super E> comparator)构造 TreeSet
    <Integer> set = new TreeSet<>( (num1,num2)-> { if (num1 < num2) return 1; if(num1 > num2) return -1; return 0; } ); set.add(9); set.add(1); set.add(3); for (int num : set){ System.out.println(num); } }

    输出

    3.EnumSet

      所有元素必须是enum类型

      EnumSet是有序的

      不允许放入null

      没有构造器, 通过静态方法获得EnumSet

    List

    特点是元素有序,可重复,继承自Collection接口,还添加了一些根据索引操作元素的方法

      List判断2个元素相等的条件是equals方法返回true

    set方法只能用于修改集合中已经存在的值,不能新增加元素。

    使用List的sort方法进行排序

        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("张三");
            list.add("李小四");
            list.add("王大少爷");
            //集合的顺序是张三,李小四,王大少爷
            list.sort(
                    ((o1, o2) ->{
                        if(o1.length() < o2.length())
                            return 1;
                        if(o1.length() == o2.length())
                            return 0;
                        return -1;
                    } )
            );
            for (String s: list) {
                System.out.println(s);            
            }
        }

     输出

     使用ListIterator迭代

    ListIterator()方法返回一个ListIterator,ListIterator增加了向前迭代元素的方法,以及添加元素的方法

       public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("张三");
            list.add("李小四");
            list.add("王大少爷");
            //集合的顺序是张三,李小四,王大少爷
            ListIterator<String> listIterator = list.listIterator();
            //注意这里调用add方法采用的是头插法
            listIterator.add("周杰伦");
            System.out.println(list);
            while(listIterator.hasNext()){
                listIterator.next();
            }
            System.out.println("你还想怎么样啊,到底了");
            System.out.println("========================");
            System.out.println("我还能反着遍历元素啊");
            while(listIterator.hasPrevious()){
                System.out.println(listIterator.previous());
            }
        }

    输出

     ArrayList,Vector

    ArrayList,Vector是List的2个典型实现,调用不带参数构造方法,initialCapacity=10;带参数的构造方法,自己指定initialCapacity

    ArrayList不是线程安全的,Vector是线程安全的

    Queue

    数据结构:队列(FIFO)

    不允许随机访问

    element()方法返回头元素,不删除集合中元素

    peek()方法返回头元素或者null,不删除集合中元素

    poll()方法返回头元素或者null,删除集合中元素

    1.PriorityQueue

      按元素大小重新排序,因此取出头元素时,是最小的元素

      PriorityQueue不允许插入null

      PriorityQueue对元素的排序方法同样有2种,自然排序和定制排序,思路和TreeSet一样

    2.Deque和ArrayDeque

      Deque代表一个双端队列

     

    它们功能相同,区别是对失败情况的处理不同。一套接口遇到失败就会抛出异常,另一套遇到失败会返回特殊值(falsenull

      ArrayDeque底层也是数组,数组长度默认是16

    ArrayDeque可以作为栈和队列使用(推荐)

    作为栈时使用下面2个方法操作元素

    作为队列时使用下面方法操作元素

    LinkedList

      实现了List和Deque 2个接口,底层是链表,随机访问效率较差,插入删除效率高

      LinkedList采用迭代器方式遍历效率高,ArrayList,Vector使用get效率高

    Map体系结构

     

     Map

      Key:无序,不可重复->组成一个keySet

      Value:有序,可重复->组成一个List

       public static void main(String[] args){
            Map<Integer,String> map = new HashMap<Integer,String>();
            //添加元素
            map.put(1,"张三");
            map.put(2,"李四");
            map.put(3,"王五");
            //key是唯一的,如果放入相同的key,会把现有的覆盖
            map.put(3,"赵子龙");
            //输出赵子龙
            System.out.println(map.get(3));
            //删除赵子龙
            map.remove(3);
            //遍历
            for (int i : map.keySet()){
                System.out.println(map.get(i));
            }
    
        }

    HashMap,Hashtable

      区别:1.HashMap线程不安全,Hashtable线程安全

         2.HashMap可以使用null作为key和value(由于key是不可重复的,因此key只能有1个可以为null,value可以有无数个),Hashtable不可以

      判定key和value是否相等

      判定key相等通过equals()方法和hashCode()方法,判定value相等通过equals()方法

     

    class MyKey{
        private int key;
    
        public MyKey(int key){
            this.key = key;
        }
        @Override
        public boolean equals(Object obj) {
            MyKey k = (MyKey) obj;
            if(key == k.key)
            return true;
            return false;
        }
    
        @Override
        public int hashCode() {
            return key;
        }
    }
    public class Test {
        public static void main(String[] args){
            Map<MyKey,String> map = new HashMap<>();
            map.put(new MyKey(1),"张三");
            map.put(new MyKey(2),"李四");
            //key相同,会覆盖原来的
            map.put(new MyKey(1),"周杰伦");
            //输出{MyKey@1=周杰伦, MyKey@2=李四}
            System.out.println(map);
            //返回true
            System.out.println(map.containsValue("李四"));
        }
    }

    LinkedHashMap

      LinkedHashMap使用双向链表维护key,确保key插入顺序与迭代顺序一致

    Properties

      Properties相当于一个key,value都是String的Map

      使用Properties读取配置文件

        public static void main(String[] args){
            Properties properties = new Properties();
            try {
                properties.load(new InputStreamReader(new FileInputStream("properties"),"utf-8"));
                System.out.println(properties);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

     TreeMap

      数据结构:红黑树

      每个key-value对作为红黑树节点

      2种排序方式:自然排序和定制排序(看key,与TreeSet判等规则一致)

    WeakHashMap

      与HashMap区别:WeakHashMap的key中保存的是弱引用,HashMap中保存的是强引用

      如果WeakHashMap中的key没有被其他强引用变量引用,这些key有可能被GC回收

    IdentityHashMap

      与HashMap区别:IdentityHashMap只有当key1 == key2 才认为2个key相等,HashMap两个key的equals,hashCode相等即相等

    工具类Collections

     对List的操作

     public static void main(String[] args){
            List<Integer> list = new ArrayList<>();
            for (int i=0; i<10;i++){
                list.add(i);
            }
            //输出[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
            System.out.println(list);
            //逆序
            Collections.reverse(list);
            //输出[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
            System.out.println(list);
            //随机排序
            Collections.shuffle(list);
            System.out.println(list);
            //升序排序
            Collections.sort(list);
            System.out.println(list);
            //二分查找指定元素位置,List必须有序
            System.out.println(Collections.binarySearch(list,5));
        }

      查找Collection最大最小值

        public static void main(String[] args){
            Collection<Integer> c = new HashSet<>();
            for (int i=0;i<10;i++){
                c.add(i);
            }
            //最大值9
            System.out.println(Collections.max(c));
            //最小值0
            System.out.println(Collections.min(c));
        }

      同步集合

      

    通过上面3个方法得到同步后的集合,确保线程安全

  • 相关阅读:
    sql server 2008数据库 降为 sql server 2005数据库 最终方案总结
    android 单元测试
    C# 5.0中引入了async 和 await
    Android之NDK开发
    Java NIO原理 图文分析及代码实现
    【第六篇】Volley之https相关
    【第五篇】Volley代码修改之图片二级缓存以及相关源码阅读(重写ImageLoader.ImageCache)
    【第四篇】Volley修改之GsonRequest
    java复习 --集合类
    android 图片加载优化,避免oom问题产生
  • 原文地址:https://www.cnblogs.com/vshen999/p/8365947.html
Copyright © 2011-2022 走看看