美文网首页
Java集合(二)

Java集合(二)

作者: 浮桥小麦 | 来源:发表于2017-06-15 16:15 被阅读10次
    1. List集合简单使用
    //学习Collection子类List的一些特有方法的使用
            //1.创建,还是采用父类引用指向子类对象,开发中一般直接用子类
            List lt = new ArrayList();
    
            //2. void add(int index, E element):在指定位置添加元素
            lt.add("a");
            lt.add("b");
            lt.add("d");
             //在指定位置添加元素
            lt.add(2,"c");//index可以小于等于size()并且大于等于0;
            System.out.println(lt);
    
            //3. E remove(int index):移除指定位置的元素,返回被删除的那个元素
            lt.remove(2);
            System.out.println(lt);
            //这里我们举个例子有问题的情况
            List lt1 = new ArrayList();
            lt1.add(11);
            lt1.add(23);
            lt1.add(45);//我们将这几个整数加入到集合中
            //来用哈删除方法
            //Object ob3 = lt1.remove(11);//这样写运行就会报错,我们的本意
            //也许就是想删除我们加入到集合中的11元素,但是在加入集合时,有自动装箱
            //而在这里传值进来却没有自动装箱,所以系统会将这个11当成索引使用,那么就会越界报错
    
            //4. E get(int index):获取指定位置的元素
            Object ob = lt.get(2);//这个方法可以用来做遍历,这是List集合中特有的遍历方式
            System.out.println(ob);
    
            //5. E set(int index, E element):给集合中指定位置的元素赋值,并返回改变之前这个位置的元素值
            Object ob1 = lt.set(2,"jj");
            System.out.println(ob1);
            System.out.println(lt);
    
    
    2. 并发修改异常产生的原因和处理
    //1.需求:我有一个集合,请问我想判断里面有没有"world"元素,有就向集合里面添加一个"javaEE"元素
            List lt = new ArrayList();
            lt.add("a");
            lt.add("b");
            lt.add("d");
            lt.add("world");
            lt.add("f");
            //迭代器遍历
            //Iterator it = lt.iterator();
            //用专门操作List集合的迭代器
            ListIterator lir = lt.listIterator();
            while (lir.hasNext()){
                //用String来记录这个it.next()
                String str = (String)lir.next();
                //判断是否有world元素
                if (str.equals("world")){
                   //有,就向集合中添加一个元素
                   // lt.add("javaEE");
                    //出错原因解释:我们的集合中原来就5个元素,拿给迭代器去负责展示,但是
                    //在迭代器展示元素的过程中,我们又去给集合增加了一个元素,这样就造成了并发修改
                      lir.add("javaEE");
                }
            }
            System.out.println(lt);
            //错误显示:java.util.ConcurrentModificationException:并发修改异常:当方法检测到对象的并发修改,
            //但不允许这种修改时,抛出此异常
            //解决问题:我们可以利用迭代器自己有的方法来帮助我们修改集合中的元素
    
    
    3. 简单学习ListIterator(了解反向遍历)
     //ListIterator简单操作
            List lt = new ArrayList();
            lt.add("a");
            lt.add("b");
            lt.add("d");
            lt.add("world");
            lt.add("f");
            //用专门操作List集合的迭代器
            ListIterator lir = lt.listIterator();
            while (lir.hasNext()){
    
                System.out.println(lir.next());//获取元素,并将指针向后移动
            }
            System.out.println("-------------------");
    
            while (lir.hasPrevious()){//判断是否有前一个
                System.out.println(lir.previous());//获取元素,并将指针向前移动--相当于反向遍历
            }
            //会出现的问题:如果我们把正向遍历的代码注释掉的话,会发现调用反向遍历的代码也没有作用。
            //这是因为没有正向遍历的话,集合指针是指向0这个索引的,我们来向前遍历的话,就会到-1,那就没有元素,所以直接没有返回了
    
    4. 数组和链表
    1.数组:查询快,修改快,但是增和删操作慢(ArrayList)
    2.链表:查询,修改满, 增删快(LinkedList)
    3.List的三个子类的特点:
    
    ArrayList:
     底层数据结构是数组,查询快,增删慢
    线程不安全,效率高
    Vector:
    底层数据结构是数组,查询快,增删慢
    线程安全,效率低
    Vector相对ArrayList查询慢(线程安全)
    Vector相对LinkedList增删慢(数据结构)
    
    LinkedList:
    底层数据结构是链表,查询慢,增删快。
    线程不安全,效率高。
    
    Vector和ArrayList的区别:
    Vector是线程安全的,效率低
    ArrayList是线程不安全的,效率高
    
    ArrayList和LinkedList的区别:
    ArrayList底层数据结构,查询和修改快
    LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
    
    //我们如何使用List的三个子类呢?
    查询多用:ArrayList
    增删多用:LinkedList
    都多用:ArrayList
    
    
    5. 去除ArrayList中的重复元素
     //去除ArrayList中的重复元素的方式
            //思路:创建新集合的方式
            ArrayList lt = new ArrayList();
            lt.add("a");
            lt.add("b");
            lt.add("j");
            lt.add("world");
            lt.add("f");
            lt.add("b");
            lt.add("b");
            lt.add("j");
            lt.add("j");
            lt.add("world");
    
          ArrayList newList = getSingleArr(lt);
            System.out.println(newList);
        }
        //单独抽取一个方法
        public static ArrayList getSingleArr(ArrayList arrl){
                //创建一个新集合
            ArrayList newList = new ArrayList();
            //获取老集合的迭代器
            Iterator it = arrl.iterator();
            //遍历这个老集合
            while (it.hasNext()){
                Object ob = it.next();
                if (!newList.contains(ob)){
                    newList.add(ob);
                }
    
            }
            return newList;
        }
    
    6. 对于自定义对象在ArrayList中的去重
    首先定义一个自定义类
    public class Student {
    
        //两个私有成员变量
        private String name;
        private int age;
        //空参构造
        public Student() {
            super();
        }
        //有参构造
        public Student(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;
        }
        //重写toString方法
        @Override
        public String toString() {
            return "Student [name=" + name + ", age=" + age + "]";
        }
    
        @Override
        public boolean equals(Object obj){
           //比较字面值,不比较地址
            Student s = (Student)obj;
           if (this.name.equals(s.name) && this.age == s.age){
               return true;
           }else{
               return false;
           }
    
        }
    }
    //在实现中:
    public static void main (String[] args){
             //去除ArrayList中自定义重复对象
            ArrayList lt = new ArrayList();
            lt.add(new Student("tmac",18));
            lt.add(new Student("tmac",18));
            lt.add(new Student("kobe",18));
            lt.add(new Student("tmac",18));
            lt.add(new Student("kobe",18));
            lt.add(new Student("tmac",18));
     ArrayList newList = getSingleArr(lt);
           Iterator it = newList.iterator();
           while (it.hasNext()){
               System.out.println(it.next());
           }
    //我们传入的是自定义对象,但是同样执行我们去除重复元素的方法,打印发现并没有去除掉
            //我们仔细分析,没有去除掉应该是!newList.contains(ob)这个判断都是真。造成这个的原因是
            //我们看底层contains的实现,发现是用equals方法作比较的,而equals方法比较的是对象的地址值
            //而我们上面创建的对象,地址值都不一样,所以无法去除,解决办法就是重写Student对象的equals方法
    
    //顺带做到这里了,我们也来举个列子,我们先将Student中的重写equals方法注释掉
            //我们来删除这个newList中的对象
            newList.remove(new Student("tmac",18));
            System.out.println("****");
            System.out.println(newList);
            //你会发现这样也删不掉,那是因为remove的方法,底层一样依赖的是equals方法
    
     }
        //单独抽取一个方法
        public static ArrayList getSingleArr(ArrayList arrl){
                //创建一个新集合
            ArrayList newList = new ArrayList();
            //获取老集合的迭代器
            Iterator it = arrl.iterator();
            //遍历这个老集合
            while (it.hasNext()){
                Object ob = it.next();
                if (!newList.contains(ob)){
                    newList.add(ob);
                }
     }
            return newList;
        }
    }
    
    
    7. LinkedList的特有功能
    //LinkedList的特有功能
            /*
            * public void addFirst(E e)及addLast(E e)
            * public E getFirst()及getLast()
            * public E removeFirst()及public E removeLast()
            * public E get(int index):
            * */
    
            //1.public void addFirst(E e)及addLast(E e):
            LinkedList list = new LinkedList();
            list.addFirst("a");
            list.addFirst("b");
            list.addFirst("c");
            list.addFirst("d");
            //我们看这个我们每个元素都是放到第一位的,对于链表来说,就成了先进在后了
            System.out.println(list);
    
            list.addLast("e");
            list.addLast("f");//addLast:就是先进在前了
            System.out.println(list);
    
            //2. public E getFirst()及getLast()
            Object ob = list.getFirst();
            Object ob1 = list.getLast();
            System.out.println(ob);
            System.out.println(ob1);
            //3. public E removeFirst()及public E removeLast():删除头尾
            //4. public E get(int index):根据索引查找元素
            Object ob2 = list.get(2);
            //我们看这个get(int index):的源码,就知道为什么这个链表的查找更慢了
            System.out.println(ob2);
    
    8. 栈和队列数据结构
    栈: 先进后出
    
    队列: 先进先出
    
    LinkedList模拟栈的数据结构:
    单独封装一个Stack(栈类):
    public class Stack {
        //我们自己创建一个栈类,然后内部用LinkedList来实现进栈和弹栈
        //创建LinkedList的成员变量
        private LinkedList list = new LinkedList();
        //模拟进栈方法
        public void inStack(Object obj){
            list.addLast(obj);
        }
    
        //模拟出栈
        public  Object outStack(){
            return list.removeLast();
        }
    
        //模拟栈结构是否为空
        public  boolean isEmpty(){
            return list.isEmpty();
        }
    
        //重写Object的toString方法
        public String toString(){
            String str = new String();
            Iterator it = list.iterator();
            while (it.hasNext()){
               Object ob = it.next();
               str = str + ob + ",";
            }
           return str;
        }
    }
    //使用:
    //直接调用我们封装的Stack类
            Stack s = new Stack();
            s.inStack("a”);//这里最先加进去的元素其实是a,因为最先调用这个加入a元素的方法
            s.inStack("b");
            s.inStack("c”);//理解一下先进后出
            System.out.println(s);
            while (!s.isEmpty()){
                System.out.println(s.outStack());
            }
    
    
    9. 泛型简介
    //泛型
            /*
            * 泛型好处:
            * 提高安全性(将运行期的错误转换到编译器)
            * 免去强转的麻烦
            * 泛型基本作用:
            * <>号中放的必须是引用数据类型
            * 泛型使用注意事项:
            * 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7版本的新特性)
            * */
    
            //泛型举例说明:
            ArrayList<Student> list = new ArrayList<Student>();
    //        list.add(110);
    //        list.add(true);
            list.add(new Student("tmac",18));
            list.add(new Student("李四",24));
            //我们给集合添加了三个不同类型的值,我们来遍历一下
             Iterator<Student> it = list.iterator();
             while (it.hasNext()){
                 //System.out.println(it.next());
                 //我们这样直接遍历是没有问题的,但是如果我们想要获得Student对象中的名字,年龄,
                 //就要单独调用Student中的getName和getAge方法,如果我们直接将it.next()获得的元素
                 //直接强转为Student对象,就会出错
    //             Student s = (Student)it.next();
                 //System.out.println(s.getName() + "   " + s.getAge());
                 //报错:java.lang.ClassCastException:类型转换异常
                 //解决加泛型--其实和iOS里面的泛型是一个道理哈
    
                 Student s= it.next();
                 //最好不要直接打印it.next(),因为it.next()方法只能调用一次,调用多次会将指针向后移动
                 System.out.println(s.getName() + " 、、 " + s.getAge());
      }
    
    
    10.方法泛型的区别
    //泛型
            //普通方法
            Tool tool = new Tool();
            tool.show("我爱你");
            //静态方法
            Tool.print("我是谁”);
    
    public class Tool<T> {
        private  T t;
    
        public  T getObj(){
            return t;
        }
    
        public void setObj(T t){
            this.t = t;
        }
    
        public void show(T t){
            System.out.println(t);//方法泛型最好和类的泛型一致
                                  //如果不一致,需要在方法前声明该泛型
        }
         //对于T而言,在创建Tool的对象,给其赋值的时候,是什么类型的,T就是什么类型的
    
         //对于静态方法--必须要声明自己的泛型
        //这是因为,T是跟随Tool对象时,创建而创建,而静态方法是跟随Tool类的创建而创建的
        //如果我们将静态方法的泛型和类的泛型相同的话,很可能Tool对象还没有创建,而Tool创建了
        //这样我们静态方法的泛型就会出问题
        public static<X> void print(X x){
            System.out.println(x);
        }
        //这个一致,不是说命名相同,如果我只是在静态方法的方法名后接泛型名和类相同,是不行的
        //但是这样写是可以的:public static<T> void print(T t){}是可以的
    
    

    相关文章

      网友评论

          本文标题:Java集合(二)

          本文链接:https://www.haomeiwen.com/subject/lbieqxtx.html