在劫

吾生也有涯,而知也无涯 。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

数组存对象

package CollectionTest;

public class Student {
    //变量私有,给出get方法提供变量
    //某些属性成员变量不要让外界任意访问
    private String name;
    private int age;
    public Student(){}
    public Student(String name, int age){
        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()方法
   public String toString() {
       return "Student [name=" + name + ", age=" + age + "]";
    } }
public class ArrayDemo1 {

    public static void main(String[] args) {
        Student[] s = new Student[5];
        Student s1 = new Student("zed1",1);
        Student s2 = new Student("zed2",2);
        Student s3 = new Student("zed3",3);
        Student s4 = new Student("zed4",4);
        Student s5 = new Student("zed5",5);

        s[0] = s1;
        s[1] = s2;
        s[2] = s3;
        s[3] = s4;
        s[4] = s5;
        
        //下面代码输出哈希码,数组存储的是对象
        //for(int i = 0; i < s.length; i++){
        //    System.out.println(s[i]);
        //}
        
        for(int i = 0; i < s.length; i++){
            Student ss = s[i];
            System.out.println(ss.getName() + "---" + ss.getAge());
        }
    }

}

   数组长度是固定的,所以有时候需要用到集合。

  为什么出现集合类?
      面向对象语言对事物体现都是以对象的形式,所以为了方便对多个对象的操作,java就提供了集合类。
  数组和集合类同是容器,有何不同?
      数组虽然也可以存储对象,但长度是固定的,集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
  集合类特点
      集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

数组没有length方法,只有length属性。
字符串有length方法。
集合有size方法。

    ECLIPSE复制粘贴代码很容易把包一下导过来了,所以要注意。

public class Student {
    //变量私有,给出get方法提供变量
    //某些属性成员变量不要让外界任意访问
    private String name;
    private int age;
    public Student(){}
    public Student(String name, int age){
        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()方法,放掉注释
/* public String toString() { return "Student [name=" + name + ", age=" + age + "]"; }*/ }

  添加对象到集合的三种方式:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionTest2 {

    public static void main(String[] args) {

        Collection<Student> c = new ArrayList<>();
        
        // 三种往集合中添加对象的方法
        // 方法一
        Student s1 = new Student("zed1", 1);
        Student s2 = new Student("zed2", 2);
        c.add(s1);
        c.add(s2);
        
        //方法二
        c.add(new Student("zed3", 3));
        c.add(new Student("zed4", 4));
        
        //方法三 使用类中setter方法
        Student s5 = new Student();
        Student s6 = new Student();
        s5.setName("zed5");
        s5.setAge(5);
        s6.setName("zed6");
        s6.setAge(6);
        
        //如果对象所在类重写了toString()方法,可以直接输出,如果没有重写,输出的是哈希码
        System.out.println(c);
        
        System.out.println("-----------------------------");
        
        Iterator it = c.iterator();
        while(it.hasNext()){
            //强制转换成Student类型
            Student s = (Student)it.next();
            System.out.println(s.getName() + "-----" + s.getAge());
        }
    }

}

  clear()清空元素

        Student s1 = new Student("zed1", 1);
        Student s2 = new Student("zed2", 2);
        Student s3 = new Student("zed3", 3);

        c1.add(s1);
        c1.add(s2);
        c1.add(s3);
        
        Iterator it = c1.iterator();
        while(it.hasNext()){
            //强制转换成Student类型
            Student s = (Student)it.next();
            System.out.println("c1" + s.getName() + "--未清空元素---" + s.getAge());
        }
        //移除所有元素
        c1.clear();
        System.out.println("c1" + "--清空元素---"+ c1);

  是否包含某元素contains:

        Student s1 = new Student("zed1", 1);
        Student s2 = new Student("zed2", 2);
        Student s3 = new Student("zed3", 3);

        c1.add(s1);
        c1.add(s2);
        c1.add(s3);
        
        Student s8 = new Student("zed8", 8);
        System.out.println("是否包含某元素: "  + c1.contains(s8));//false
        System.out.println("是否包含某元素: "  + c1.contains(s1));//true

   判断集合是否为空:

        //判断集合是否包含元素,空集合返回true
        System.out.println("集合中是否包含元素(未使用clear()方法): " + c1.isEmpty());
        c1.clear();
        System.out.println("集合中是否包含元素(已使用clear()方法): " + c1.isEmpty());

  删除指定对象:  

        Student s1 = new Student("zed1", 1);
        Student s2 = new Student("zed2", 2);
        Student s3 = new Student("zed3", 3);

        c1.add(s1);
        c1.add(s2);
        c1.add(s3);
        //删除指定元素
        //未清空元素 [Student [name=zed1, age=1], Student [name=zed2, age=2], Student [name=zed3, age=3]]
        System.out.println("未清空元素 " + c1);
        c1.remove(s2);
        //清空元素s2之后 [Student [name=zed1, age=1], Student [name=zed3, age=3]]
        System.out.println("清空元素s2之后 " + c1);

  集合大小size()方法和转换成数组toArray()方法:

        Student s1 = new Student("zed1", 1);
        Student s2 = new Student("zed2", 2);
        Student s3 = new Student("zed3", 3);

        c1.add(s1);
        c1.add(s2);
        c1.add(s3);
        //集合元素数量
        System.out.println(c1.size());
        
        //转换成数组
        //强制转换成Student类型
        //Student[] s = (Student)c1.toArray(); 这个转换是错误的
        Object[] s =c1.toArray();
        for(int i = 0; i < s.length; i++){
            System.out.println(s[i]);
        }

   求交集、并集等:

        Student s1 = new Student("zed1", 1);
        Student s2 = new Student("zed2", 2);
        Student s3 = new Student("zed3", 3);

        c1.add(s1);
        c1.add(s2);
        c1.add(s3);
        
        Student s4 = new Student("zed4", 4);
        Student s5 = new Student("zed5", 5);
        Student s6 = new Student("zed6", 6);
        c2.add(s4);
        c2.add(s5);
        c2.add(s6);
        
        //将一个集合添加到另一个集合中,添加成功返回true
        System.out.println("是否添加成功 " + c1.addAll(c2));
        for(Student c : c1){
            System.out.println(c);
        }
        
        //判断集合中是否包含另一集合所有元素
        System.out.println("是否包含另一个集合所有元素 " + c1.containsAll(c2));
        
        //仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作),求交集
        //删除掉另一集合不包含的元素,如果删除成功返回true。
        System.out.println("求交集 " + c1.retainAll(c2));
        System.out.println("求交集删除成功,输出交集 " + c1);
        
        //删除c1集合和c2集合的交集
        c1.removeAll(c2);
        System.out.println("删除交集元素之后输出 " + c1);

迭代器

  迭代器是遍历集合的一种方式
  迭代器是依赖于集合而存在的
  迭代器为什么不定义成一个类,而是一个接口?
   Java提供很多集合类,这些集合类的数据结构是不同的,存储方式和遍历的方式应该是不同,进而它们的遍历方式也应该不一样。
   在真正的具体实现在子类的内部类中

  迭代的三种方法:

  迭代的时候要注意强制转换数据类型。

        Collection<Student> c = new ArrayList<>();
        
        Student s1 = new Student("zed1", 1);
        Student s2 = new Student("zed2", 2);
        Student s3 = new Student("zed3", 3);
        
        c.add(s1);
        c.add(s2);
        c.add(s3);
        
        //方法一
        Iterator<Student> it = c.iterator();    
        while(it.hasNext()){
            //强制数据类型转换
            Student s = (Student)it.next();
            System.out.println(s);
        }
        
        //方法二
        //这种方法效率最高,for循环完迭代器就编程垃圾了
        //for(初始化语句; 条件语句; 此处可以为空)
        for(Iterator<Student> it = c.iterator(); it.hasNext(); ){
            System.out.println(it.next());
        }
        
        //方法三
        for(Object obj : c){
            //for each两种方式都可以,如果是调用对象方法的话,要强制进行类型转换
            //System.out.println(obj);
            System.out.println(((Student) obj).getName() + "----" + ((Student) obj).getAge());
        }

  迭代器中使用remove()方法,删除的是集合中的元素,而不只是迭代器中的。

        Iterator<Student> it = c.iterator();    
        while(it.hasNext()){
            System.out.println(it.next());
            it.remove();
            
        }
        System.out.println("迭代器使用remove方法之后,集合中元素的个数为: " +c.size());

  上面程序如果先调用remove()方法,再调用next()方法,会抛出IllegalStateException错误。

        Iterator<Student> it = c.iterator();    
        while(it.hasNext()){
            //下面是将it.next()强制转换成Student类型
            System.out.println(((Student)it.next()).getName() + "------" + ((Student)it.next()).getAge());
            //请注意,上面命令,((Student)it.next()).getName()和((Student)it.next()).getAge()得到的变量不属于同一个对象
            //因为getAge()已经是第二次调用next()方法了
        }

List

  List接口概述
      有序的Collection(也成为序列)。此接口用户可以对列表中的每个元素的插入位置进行精确控制。用户可以根据元素的整数索引访问元素,并搜索列表中的元素。
      与set不同,列表通常允许重复的元素
  List案例
      存储字符串并遍历
      存储自定义对象并遍历
  List集合特点
      有序(存储和取出的元素一致),可重复的。

        List<String> l = new ArrayList<>();
        
        //可重复,放入取出顺序一致
        l.add("java");
        l.add("jse");
        l.add("jee");
        l.add("jee");
        
        Iterator it = l.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

  List相比Collection增加的几种方法:

        List<String> l = new ArrayList<>();
        l.add("1---java");
        l.add("2---jse");
        l.add("3---jee");
        l.add("3---jee");
        
        //在指定位置添加元素
        l.add(0, "hello");
        Iterator it = l.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("------------------------");
        
        //获取指定位置的元素
        System.out.println("获取指定位置的元素  " + l.get(2));
        
        //返回第一次出现位置的索引
        System.out.println("第一次出现指定元素的索引 " + l.indexOf("3---jee"));
        //如果不包含该元素返回-1
        System.out.println("第一次出现指定元素的索引,不包含jee,返回-1   : " + l.indexOf("jee"));
        
        //返回列表中最后出现指定元素的索引
        System.out.println("最后一次出现指定元素的索引 " + l.lastIndexOf("3---jee"));
        
        //移除列表中指定位置的元素,并返回该元素
        System.out.println("移除指定位置的元素并返回 " + l.remove(4));
        System.out.println(l);
        
        //用指定元素替换列表中指定元素,并返回
        System.out.println("替换元素" + l.set(3, "JavaEE"));
        System.out.println(l);
        
        //List<E> subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图
        List l2 = l.subList(1, 3);
        System.out.println(l2);

  List特有遍历功能:

/*
    List特有遍历功能:
        size()和get()方法结合
    */
for(int i = 0; i < list.size(); i++){
    String s = (String)list.get(i);
    System.out.println(s);
    }

  ListIterator一般不使用

        List<String> l = new ArrayList<>();
        l.add("1---java");
        l.add("2---jse");
        l.add("3---jee");
        //listIterator继承了Iterator,所以可以用hasNext()和Next()
        //这样没有任何意义,要实现逆向遍历必须先正向遍历,因为指针在正向开始处
        ListIterator lit = l.listIterator();
        while(lit.hasPrevious()){
            String s = (String)lit.previous();
            System.out.println(s);
        }
    }
迭代器是依赖于集合存在的,在判断成功后,集合中新添加了元素.
而迭代器却不知道,所以就报错了。这个错叫并发修改异常
其实这个问题描述的是迭代器遍历元素的时候,通过集合是不能修改元素的。
            List<String> l = new ArrayList<>();
            l.add("1---java");
            l.add("2---jse");
            l.add("3---jee");
            Iterator it = l.iterator();
            while(it.hasNext()){
                String s = (String)it.next();
                //此处会发生并发修改异常
                if("world".equals(s)){
                    list.add("javaee");
                    }
                }
如何解决呢?
    A、迭代器遍历的时候,用迭代器修改元素;
            元素是跟在刚才迭代元素的后面的
                    List<String> l = new ArrayList<>();
                    l.add("1---java");
                    l.add("2---jse");
                    l.add("3---jee");
                    ListIterator it = l.listLterator();
                    while(it.hasNext()){
                        String s = (String)it.next();
                        if("world".equals(s)){
                            it.add("javaee");
                            }
                        }
    B、集合遍历元素,集合修改元素(普通for)

 

 List:
    ArrayList:底层是数组 增删慢 查询快 线程不安全 效率高
    Vector:底层是数组 增删慢 查询快 线程安全 效率低
    LinkedList:底层是链表 增删快 查询慢 线程不安全 效率高

 

 

 

posted on 2017-05-11 07:59  长嘴大耳怪  阅读(187)  评论(0编辑  收藏  举报