• java的集合框架


    1, java类集的整个体系的组成和关系,以及各个接口,类的文字说明:

    集合框架的特征:高性能,对动态数组,链接表,树和散列表的实现是高性能,允许不同类型的类集以相同的方式工作.它不受对象数组长度的限制

    Collection:

      -|:List  里面的内容是有序的(存入和取出的顺序一致),允许重复的内容,有索引,它扩充了Collection接口,拥有更多的方法

         --|:ArrayList  内部是数组数据结构,查询速度快,不同步,判断元素是否存在,删除元素,底层用的是equals方法

         --|:LinkedList  内部是链表数据结构,增删的速度快,也是不同步的

      -|:Set  不能存放重复的内容,是无序的,

        --|:HashSet  不能存放重复的元素,采用散列的储存方式,没有顺序,判断元素是否存在,删除元素,底层用的是equals和hashcode方法

        --|:TreeSet   不能存放重复的元素,输出的数据是有序的

    ------------------------------------------------------------------------------------------------------------------

    名称 数据结构 是否有序 是否同步(安全) 特点
    ArrayList 数组 有序 不同步 按照索引查询速度快
    LinkedList 链表 有序 不同步 增删速度快
    Vector 数组 有序 同步 线程安全,按照索引查询速度快
    TreeSet 二叉树 无序(可以提供比较器) 不同步 根据比较器自定义排序
    HashSet 哈希表 无序 不同步 按照内容查询速度快

    -------------------------------------------------------------------------------------------------------------------

    package cn.wjd.ArrayList;
    import java.util.ArrayList;
    import java.util.Iterator;
    import cn.wjd.bean.Person;
    public class ArrayListTest {
        public static void main(String[] args) {
            ArrayList a1 = new ArrayList();
            a1.add(new Person("zhangsan1",21));//存自定义对象的时候,需要强转
            a1.add(new Person("zhangsan2",22));
            a1.add(new Person("zhangsan3",23));
            a1.add(new Person("zhangsan4",24));
            Iterator it = a1.iterator();
            while (it.hasNext()) {
    //            System.out.println(((Person) it.next()).getName()); 这段代码具有局限性,在循环中,一个对象调用2次方法,会出现异常
                Person p = (Person) it.next();//解决方法,得到一个对象,然后使用对象进行调用方法
                System.out.println(p.getName() +"-->" + p.getAge());
            }
        }
    }

    以上ArrayList代码中,两个注意点,我这边在ArrayList的容器中,加入的是自定义的对象,所以在输出数据的时候,一定要进行强制转换,强转得到对象,输出对象内容,这两个步骤一定要分开走,否则假如是一步走的话在while循环的输出会出现异常.

    由以上代码,引出集合的标准输出的方法,Iterator(迭代输出,使用最多的输出方式)和ListIterator(专门用于输出List中的内容).

    2, 在ArrayList的集合中去掉重复的元素,同理还有另外一个需求,去掉一个数组中重复的元素,请看下面的代码

    去掉集合中的重复元素

    package cn.arraylist;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;
    
    public class ArrayList02 {
        public static void main(String[] args) {
            List<String> list = new ArrayList<String>();
            list.add("a");
            list.add("a");
            list.add("b");
            list.add("b");
            list.add("c");
            list.add("c");
            List<String> li = getSingleElement(list);
            System.out.println(li);
        }
    
        public static List<String> getSingleElement(List<String> list) {
            ArrayList<String> temp = new ArrayList<String>();
            ListIterator<String> it = list.listIterator();
            while(it.hasNext()){
                String str = it.next();
                if(!temp.contains(str))
                    temp.add(str);
            }
            return temp;
        }
    
    }

    去掉数组中的重复元素

    package cn.demo;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    
    //数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
    public class Demo2 {
        public static void main(String[] args) {
            int[] arr = {4,2,4,6,1,2,4,7,8};
            List<Integer> list = new ArrayList<Integer>();
            for(int i : arr){
                if(!list.contains(i))
                    list.add(i);
            }
            System.out.print(list);

    其实上面两段代码,使用到的思路是一样的,给定一个集合或者数组的时候,我们要改变它的长度,这个肯定是要考虑到用集合去解决的,因为数据的长度是不可以改变的,所以都得定义一个集合变量,来存储最后不重复的元素.

    在去掉数组中重复元素的话,还有一个更加牛逼的方法,先将数组遍历装到ArrayList集合中(就算是int型的数组,它会自动变成Integer),然后把ArrayList这个数组中的元素全部添加到HashSet集合中去,由于HashSet的特点,所以直接去掉了重复元素,不过最后打印的数据的排列顺序会有点变化.你懂的.

    package cn.demo;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.ListIterator;
    import java.util.Set;
    
    //数组去重复,例如: 原始数组是{4,2,4,6,1,2,4,7,8},得到结果{4,2,6,1,7,8}
    public class Demo01 {
        public static void main(String[] args) {
            int[] arr = {4,2,4,6,1,2,4,7,8};
            List<Integer> al = new ArrayList<Integer>();
            for(int i : arr){
                al.add(i);
            }
            
            Set<Integer> set = new HashSet<Integer>();
            set.addAll(al);
            System.out.println(set);
        }
    }

    迭代输出:Iterator(迭代含义:一个个对集合中的内容进行判断,有内容就将其取出)

    最标准的做法,只要碰到集合输出,一定要想到这个接口.标准输出代码如下:

    Iterator it = col.iterator();  //Collection中的方法,返回Iterator对象
    while(it.hasNext()){           //Iterator对象进行迭代判断,是否有下一个值
        System.out.println(it.next());// 挨个取出当前元素
    }

     

    双向迭代输出:ListIterator(List专用的,只能通过List接口实例化,只能输出List接口中的内容)

    package cn.wjd.List;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.ListIterator;
    public class ListDemo02 {
        public static void main(String[] args) {
            List list = new ArrayList();
            //show(list);
            list.add("abc1");
            list.add("abc2");
            list.add("abc3");
            System.out.println("原来的-->" + list);
            ListIterator it = list.listIterator();  //获取列表迭代器对象,它在迭代的过程中,可以完成对元素的增删改查,这个是list集合特有的
            while (it.hasNext()) {       //使用列表迭代器,操作的对象是迭代器对象,不是集合对象  
                Object obj = it.next();   
                if(obj.equals("abc2"))
                    it.add("abc4");
                else                 
                    System.out.println("next -->" + obj);
                    
            }
            System.out.println("列表迭代器迭代之后的-->" + list);
            
        /*    list.add("abc1");
            list.add("abc2");
            list.add("abc3");
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Object obj = it.next();   //java.util.ConcurrentModificationException
                if(obj.equals("abc2"))//在进行迭代操作的时候,不能进行集合的操作,这样容易出现异常,如,迭代的话知道集合的元素个数,
                    list.add("abc4");//再进行集合操作,元素个数会发现变化,这样就出现了异常
                else                 //解决方法,使用ListIterator接口来完成
                    System.out.println("next -->" + obj);
                    
            }*/
        }
        public static void show(List list) {
            list.add("abc1");
            list.add("abc2");
            list.add("abc3");
            list.add("abc4");
            Iterator it = list.iterator();
            while (it.hasNext()) {
                System.out.println("next-->" + it.next());
            }
            //List中特有的取数的方法,get()方法
            for (int i = 0; i < list.size(); i++) {
                System.out.println("get-->" + list.get(i));
            }
        }
    }

    先看API中List接口中一个特殊的方法:2

    在List中,有了该方法,它就存在一个特有的取数方式,利用for循环,循环次数为List集合对象的长度,然后通过该方法循环输出.

    List集合只能使用ListIterator进行输出的原因(ConcurrentModificationException 异常出现的原因):我们在进行迭代操作的时候,如果集合的引用和迭代器对象同时来操作容器中的内容,通过集合获取到的对应的迭代器,然后对集合进行增删改查的操作,假如使用之前的Iterator迭代的话,这个接口中是没有增删改查的方法的,这个时候我们只能使用它的子接口ListIterator来完成输出,直接查阅API中ListIterator的内容就了然了.

    ------------------------------------------------------------------------------------------------------------------------------------------------

    Set下面的小弟TreeSet它是如何实现有序排放的?

    1:让元素具有自己的比较功能,实现Comparator接口,通过覆盖其compare(T o1,T o2)比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数的方法,来自己建立2个对象比较的准则

    int compare(T o1,T o2)比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。

    package cn.wjd.treeset;
    import java.util.Iterator;
    import java.util.TreeSet;
    import cn.wjd.bean.Person;
    public class TreeSetDemo {
        public static void main(String[] args) {
            TreeSet ts = new TreeSet(new ComparatorByName());//构造方法中直接传入已经定义好的比较器对象
            ts.add(new Person("zhangsan",22));
            ts.add(new Person("zhangsan",21));
            ts.add(new Person("bhangsan4",24));
            ts.add(new Person("a3",22));
            ts.add(new Person("dhangsan5",25));
            Iterator it = ts.iterator();
            while (it.hasNext()) {
                Person p = (Person)it.next();
                System.out.println(p.getName() + "-->" + p.getAge());
            }
        }
    package cn.wjd.treeset;
    import java.util.Comparator;
    import cn.wjd.bean.Person;
    public class ComparatorByName implements Comparator {
        public int compare(Object o1, Object o2) {
            Person p1 = (Person)o1;
            Person p2 = (Person)o2;
            int temp = p1.getName().compareTo(p2.getName());//compareTo是String类中的方法,按照字典的顺序比较2个字符串
            return temp == 0?p1.getAge() - p2.getAge():temp;
        }//该自定义的比较器中,优先比较的是Person对象的姓名,然后再比较的是Person对象的年龄
    
    }

    小插曲,关于三目运算符的格式:表达式1?表达式2:表达式3;  当表达式1是true的时候,执行表达式2,false时,执行表达式3.

    一般表达式1是关系运算符或者是逻辑运算符.

    2,让元素自身据有比较的功能,定义类的时候,直接让它实现Comparable接口,同时复写它的compare(T o)方法

    package cn.wjd.bean;
    
    public class Person implements Comparable {
        private String name;
        private int age;
        
        @Override
        public boolean equals(Object obj) {
            Person p = (Person)obj;
            return this.name.equals(p.name) && this.age == p.age ;
        }
        @Override
        public int hashCode() {
            
            return name.hashCode() + age;
        }
        
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        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 int compareTo(Object o) {
            Person p = (Person)o;
    //        int temp = this.age - p.age;
    //        return temp == 0?this.name.compareTo(p.name):temp;
            int temp = this.name.compareTo(p.name);
            return temp == 0?this.age - p.age:temp;
            /*if(this.age > p.age)
                return 1;
            if(this.age < p.age)
                return -1;
            return 0;*/
        }
        
    }

    一般第一种方法灵活,在开发中,第一种使用的比较多

     

    HashSet

    它的底层数据结构是哈希表,线程不同步,无序,高效.

    如何确定该集合中元素的唯一性?
                     是通过对象的hashcode和equals方法来完成对象的唯一性
                     如果对象的hashcode值不同,就不需要判断equals方法
                     如果对象的hashcode值相同,则需要判断equals方法,记住hashcode是第一步,equals是第二部
                     true,视为相同元素,false,视为不同元素
                     记住,元素要存储在HashSet中,必须要覆盖hashcode和equals方法

    关于java中的哈希表

    1,对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值

    2,哈希值就是这个元素的位置。

    3,如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。

    4,存储哈希值的结构,我们称为哈希表。

    5,既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。

    ----------------------------------------------------------------------------------------------------------------------------------------------

    Map集合

    Map集合中存储的是一对元素(key->value),key和value都有对应的映射关系,要保证Map集合中key的唯一性.

    Map常用的子类
       --|Hashtable:内部结构哈希表,是同步的。不允许null作为键,作为值
          --|Properties类:用来存储键值对型配置文件的信息,可以和IO技术相结合
       --|HashMap:内部结构是哈希表,不是同步的。允许null作为键,作为值
       --|TreeMap:内部结构是二叉树,不同步,可以对Map中的键进行排序

    Map.Entry接口简介

    Map.Entry接口是Map内部定义的一个接口,专门用来保存key->value的内容,直白一点,在Map集合中插入的就是一个Map.Entry的实例化对象

    ----------------------------------------------------------------------------------------------------------------------------------------

    集合 数据类型 是否有序 是否重复 key允许null
    HashMap 哈希表 无序 不允许重复 最多一个
    TreeMap 二叉树

    有序

    不允许重复 不允许
    Hashtable 哈斯表 无序 不允许重复 最多一个

    ----------------------------------------------------------------------------------------------------------------------------------------

    Map集合的输出方式:

    由于Map它没有自己的迭代器,所以在输出的时候,需要转化成Set集合,然后再进行迭代输出.

    方式1  23

    方式2 12

    package cn.wjd.map;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    public class MapDemo {
        public static void main(String[] args) {
            Map<Integer,String> map = new HashMap<Integer, String>();
            //method(map);
            method_2(map);
        }
        
        public static void method_2(Map<Integer, String> map) {
            map.put(2, "zhangsan2");
            map.put(1, "zhangsan1");
            map.put(3, "zhangsan3");
            map.put(6, "zhangsan6");
            map.put(5, "zhangsan5");
            /*Map集合第一种取出方式
             * 对Map集合进行输出,因为Map集合没有迭代器
             * 1,通过Map集合中的keySet方法,来返回Map集合中的key元素的Set集合
             * 2,使用Set集合中的迭代,对Map中的key进行迭代输出
             * 3,使用Map中的get(key)方法,来取出Map中的所有元素内容
             */
            /*Set<Integer> keyset = map.keySet();
            Iterator<Integer> it = keyset.iterator();
            while (it.hasNext()) {
                Integer key = it.next();
                String value = map.get(key);
                System.out.println(key + "-->" + value);
                
            }*/
        /*
         * Map集合的第二种取出方法
         * 也是通过Map转换成Set,进行迭代取出
         * 使用Map中的entrySet方法,来返回包含映射关系的Set视图
         * 再使用Map.EntrySet接口中的getKey和getValue方法,来取出Map中的元素
         */
            
            Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
            Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
            while (it.hasNext()) {
                Map.Entry<Integer, String> me = it.next();
                System.out.println(me.getKey() +"-->" +me.getValue());
                
            }
            
        }
        public static void method(Map<Integer,String> map){
            System.out.println(map.put(8, "zhangsan"));
            System.out.println(map.put(8, "lisi"));
            System.out.println(map);
        }
    }
  • 相关阅读:
    分布式框架服务调用超时设计与实现
    分布式框架灰度发布实现
    写给自己的 SOA 和 RPC 理解
    Java 基础【19】代理
    Java 基础【18】 反射与内省
    Spring HttpInvoker 从实战到源码追溯
    Lombok 使用攻略
    Guava Preconditions 工具参数前置校验
    CAS 单点登录【2】自定义用户验证
    Hibernate 离线对象构建通用查询
  • 原文地址:https://www.cnblogs.com/driverwjd/p/3879220.html
Copyright © 2020-2023  润新知