美文网首页
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集合介绍

    java 集合基本概念​​​​ 在《Java核心编程技术(第二版)》中是这样介绍java集合的: java中的集合...

  • 集合概述

    一:集合的UML类图 二:集合工具的分析 (Java集合是java提供的工具) 常用的数据结构: 集合、链表、队列...

  • 一篇文章,全面解读Android面试知识点

    Java Java基础 Java集合框架 Java集合——ArrayList Java集合——LinkedList...

  • 收藏夹

    博文 Java 集合:Java 集合学习指南 Java 集合:Java 集合源码剖析 HashMap:HashMa...

  • Java集合(二)

    1. List集合简单使用 2. 并发修改异常产生的原因和处理 3. 简单学习ListIterator(了解反向遍...

  • Java 集合框架_开篇

    Java 集合框架系列 Java 集合框架_开篇Java 集合框架_ListJava 集合框架_ArrayList...

  • Java 集合框架_List

    Java 集合框架系列 Java 集合框架_开篇Java 集合框架_ListJava 集合框架_ArrayList...

  • java集合(二)——集合 Set

    一、HashSet类HashSet简介 HashSet是Set接口的典型实现,实现了Set接口中的所有方法,并没有...

  • 集合学习

    一、什么是集合 java集合类存放于java.until包下,是用来存放数据的一种容器。 二、集合与数组的区别 1...

  • java SE目录

    java SE目录 java基础(一)java基础(二)关键字面向对象(一)面向对象(二)面向对象(三)集合(一)...

网友评论

      本文标题:Java集合(二)

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