JavaSE核心API--集合类(Collection接口)

java.util.Collection

1)理论讲解:Collection接口

 java.uti.Collection接口
 Collection是所有集合的顶级接口,里面规定了所有集合都必须具备的方法
 集合和数组一样都用来保存一组元素,但是集合提供了操作元素的相关方法,使用更便捷
 Collection下面有两个常见的子接口
 java.util.List:可重复集合
 java.util.Set:不可重复集合
 重复指的是元素是否可以重复,重复元素的判断依据是靠元素自身equals比较的结果

代码演示:

    /*
     * 数组在创建时要指定元素,后面要添加还必须扩容
     */
    Collection c=new ArrayList();
    /**最好存类型一样的元素*/
    /*
     * boolean add(E e)
     */
    c.add("one");
    c.add("two");
    c.add("three");
    c.add("four");
    c.add("five");
    System.out.println(c);
    /*
     * size表示集合元素的个数,元素有多少个,集合就有多长
     * length表示数组的长度,并不是数组元素的个数,例如长度为10的数组中的元素个数可能是0个或多个
     * int size()
     * 返回当前集合元素个数
     */
    int size=c.size();
    System.out.println("size:"+size);
    /*
     * boolean isEmpty()
     * 判断该集合是否为空集(不含有任何元素)
     */
    boolean isEmpty=c.isEmpty();
    System.out.println("isEmpty:"+isEmpty);
    /*
     * void clear()
     * 清空集合
     */
    c.clear();
    System.out.println(c);
    System.out.println("size:"+c.size());
    System.out.println("isEmpty:"+isEmpty);

2)理论讲解:集合存放的是元素的引用---对象的地址

代码演示:

    Collection c=new ArrayList();
    Point p=new Point(1,2);
    c.add(p);

    System.out.println("p:"+p);
    System.out.println("c:"+c);

    p.setX(2);
    System.out.println("p:"+p);
    System.out.println("c:"+c);

3)理论讲解:泛型

泛型在集合中使用广泛,而泛型在集合中是用来约束集合的元素类型

代码演示:

    /**创建集合对象*/
    Collection<String> c=new ArrayList<String>();
    /**往集合中添加元素*/
    c.add("one");
    c.add("two");
    c.add("three");
    c.add("four");
    c.add("five");
    System.out.println(c);
//  /**通过迭代器遍历集合*/
//  Iterator<String> it=c.iterator();
//  while (it.hasNext()) {
//      String o=it.next();
//      System.out.println(o);
//  }
    /**遍历集合*/
    for (String string : c) {
        System.out.println(string);//获取每个集合元素
    }

4)理论讲解:集合操作

代码演示:

    Collection<String> c1=new ArrayList<>();
    c1.add("java");
    c1.add("c");
    c1.add("c++");
    System.out.println("c1:"+c1);//c1:[java, c, c++]

    Collection<String> c2=new HashSet<>();
    c2.add("php");
    c2.add("js");
    c2.add("java");
    System.out.println("c2:"+c2);//c2:[java, php, js]
    /*
     * 将给定集合中的所有元素添加到当前集合中
     */
    c1.addAll(c2);//把c2中的元素都加到c1中
    System.out.println("c1:"+c1);//c1:[java, c, c++, java, php, js]

    Collection<String> c3=new ArrayList<>();
    c3.add("php");
    c3.add("c++");
//  c3.add("android");
    System.out.println("c3:"+c3);//c3:[php, c++, android]
    /*
     * 全包含:判断当前集合是否包含给定集合中的所有元素
     */
    boolean contains=c1.containsAll(c3);
    System.out.println("全包含:"+contains);//全包含:true
    /*
     * 删除交集:将c1中与c3相同元素删除
     */
    c1.removeAll(c3);
    System.out.println("c1:"+c1);//c1:[java, c, java, js]

5)理论讲解:contains方法

  判断当前集合是否包含给定元素
  boolean contains(Object o)
  判断依据是依靠自身equals比较的结果

代码演示:

    Collection c=new ArrayList();
    c.add(new Point(1,2));
    c.add(new Point(3, 4));
    c.add(new Point(5, 6));
    c.add(new Point(1, 2));

    Point p=new Point(1,2);
    Boolean contain=c.contains(p);
    System.out.println("包含:"+contain);

6)理论讲解:迭代器

  集合的遍历
  集合遍历元素采用迭代器模式
  Iterator iterator()
  该方法可以获取一个用来遍历当前集合元素的迭代器
  java.util.Iterator接口
  迭代器接口规定了所有迭代器遍历集合元素的相关操作,每个集合都提供了一个用于遍历自身元素的迭代器实现类。
  而我们无需记住他们的名字,只当它们为Interator去使用即可

  迭代器遍历集合遵循“问、取、删”的顺序遍历,其中删除不是必须的

代码演示:

    Collection c=new ArrayList();
    c.add("one");
    c.add("#");
    c.add("two");
    c.add("#");
    c.add("three");
    c.add("#");
    c.add("four");
    c.add("#");
    c.add("five");
    System.out.println(c);
    //获取遍历该集合的迭代器
    Iterator it=c.iterator();
    /*
     * 问
     * boolean hasNext()
     * 判断集合是否还有下一个元素可以获取
     */
    while (it.hasNext()) {
        /*
         * 取
         * E next()
         * 获取集合下一个元素
         */
        String o=(String)it.next();
        System.out.println(o);
        if ("#".equals(o)) {
            /*
             * 迭代器在遍历时不允许通过集合自身方法增删元素,否则会抛出异常
             */
            //c.remove();
            //迭代器的remove删除的是
            it.remove();
        }
        System.out.println(o);
    }

7)理论讲解:增强for循环

  JDK1.5 之后推出了一个特性:增强型for循环,也称为新循环
  新循环与传统for循环不同,它是用来遍历集合或数组使用

代码演示:

    String[] arr= {"one","two","three","four","five"};
    //普通for循环
    for (int i = 0; i < arr.length; i++) {
        String string = arr[i];
        System.out.println(string);
    }
    //增强型for循环
    for (String string : arr) {
        System.out.println(string);
    }
    //遍历集合
    Collection c=new ArrayList();
    c.add("one");
    c.add("two");
    c.add("three");
    c.add("four");
    c.add("five");
    System.out.println(c);
    /*
     * 新循环这个特性是java编译器认可,而非虚拟机
     * 编译器在编译源代码时若发现我们使用新循环遍历数组时,会将代码改为普通的for循环遍历
     * 若发现使用新循环遍历集合,则会改为使用迭代器方式遍历
     * 注意:使用新循环遍历集合时,不要通过集合的方法增删元素
     */
    for (Object o : c) {
        String str=(String)o;
        System.out.println(str);
    }

8)理论讲解:删除集合元素

代码演示:

Collection c=new ArrayList();
    c.add(new Point(1,2));
    c.add(new Point(3, 4));
    c.add(new Point(5, 6));
//  c.add(new Point(1, 2));

    Point p=new Point(1,2);
    c.add(p);

    System.out.println("p:"+p);
    System.out.println("c:"+c);
    /*
     * 集合的remove()方法是删除集合中与给定元素equals比较为true的元素,并且只删掉一个
     * 集合存的是元素的引用
     */
    c.remove(p);//删除元素直接掉用remove方法即可,而数组还要去找到那个元素然后删掉
    System.out.println("c:"+c);

9)理论讲解:synchronizedList方法

  线程安全的集合
  集合的工具类:java.util.Collections提供了一组静态方法,可以将给定集合转换为线程安全的

  我们常用的集合实现类:ArrayList,LinkedList,HashSet它们都不是线程安全的,如果存在并发访问时,要将它们转换

代码演示:

    List<String> list = new ArrayList<>();
    list.add("one");
    list.add("two");
    list.add("three");
    System.out.println(list);
    /*
     * 将给定的List集合转换为线程安全的
     */
    list=Collections.synchronizedList(list);
    System.out.println(list);

    Set<String> set = new HashSet<>(list);
    System.out.println(set);
    /*
     * 将给定的set集合转换为线程安全的
     */
    set=Collections.synchronizedSet(set);
    System.out.println(set);
    /*
     * API手册也有说明,一个线程安全的集合也不与迭代器遍历集合的操作互斥
     * 所以若多线程“同时”操作集合存在遍历和增删元素时,需要自行维护它们之间的互斥关系。
     * 可参考聊天室Server端操作
     */

10)理论讲解:泛型

  泛型
  JDK1.5推出的一个新特性
  泛型也称为参数化类型,允许我们在使用一个类时,指定其属性,方法参数,方法返回值的类型,使得该类的使用更符合需求,更灵活

代码演示:

public class Type<T> {
   /*
    * 泛型是编译器认可,而非虚拟机
    * 所有泛型定义的地方最终会被编译器改为Object
    * 下面有泛型定义的地方会改为:
    * private Object x;
    * 
    * public Type(Object x, Object y)
    * 
    * public Object getX()
    * 
    * public void setX(Object x)
    * 所以泛型的原型就是Object
    */
   private T x;
   private T y;
   public Type(T x, T y) {
        super();
        this.x = x;
        this.y = y;
   }
   public T getX() {
        return x;
   }
   public void setX(T x) {
        this.x = x;
   }
   public T getY() {
        return y;
   }
   public void setY(T y) {
        this.y = y;
   }
   @Override
   public String toString() {
        return "(" + x + ", " + y + ")";
   }
}

11)理论讲解:泛型的使用

代码演示:

    /*
     * 使用泛型时,编译器会做两件事
     * 1.在给泛型类型赋值时,编译器会检查该值类型是否符合泛型要求
     * 例如:
     * t1.setX(2);
     * 对于t1而言,由于泛型指定为Integer,因此编译器会检查setX()传递的参数是否为整数,不是则编译不通过
     * 2.在获取泛型类型的值时,编译器会添加向下造型的代码将其转换为泛型指定类型
     * int x1=t1.getX();
     * 实际编译后会改为:
     * int x1=(Integer)t1.getX();
     * 当然这里还触发了自动拆箱,所以实际改为了
     * int x1=((Integer)t1.getX()).intValue();
     */
    Type<Integer> t1=new Type<Integer>(1,2);//在创建的同时指定参数类型
    t1.setX(2);
    int x1=t1.getX();
    System.out.println("x1:"+x1);
    System.out.println("t1:"+t1);

12)理论讲解:使用泛型的注意事项

  泛型在使用时可以不指定,若不指定则默认为原型Object
  但通常有泛型的地方都应当指定泛型的实际类型

代码演示:

    Type<Integer> t1=new Type<Integer>(1,2);//在创建的同时指定参数类型
    t1.setX(2);
    int x1=t1.getX();
    System.out.println("x1:"+x1);
    System.out.println("t1:"+t1);

    Type t2=t1;
    System.out.println("t2:"+t2);
    t2.setX("一");//此处把x类型改为了String
    Object x2=t2.getX();
    System.out.println("x2:"+x2);
    System.out.println("t2:"+t2);

    System.out.println("t1:"+t1);

//  x1=t1.getX();//类造型异常---此处x的类型是String,而x1是int型,两者不能互转
    System.out.println("x1:"+x1);
    System.out.println("t1:"+t1);

附件:作为集合元素测试集合相关操作

/**
* 作为集合元素测试集合相关操作
* 
* @author Administrator
*
*/
public class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
        super();
        this.x = x;
        this.y = y;
   }

   public int getX() {
        return x;
   }

   public void setX(int x) {
        this.x = x;
   }

   public int getY() {
        return y;
   }

   public void setY(int y) {
        this.y = y;
   }

   @Override
   public String toString() {
        return "(" + x + ", " + y + ")";
   }

   @Override
   public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
   }

   @Override
   public boolean equals(Object obj) {
        if (this == obj)
           return true;
        if (obj == null)
           return false;
        if (getClass() != obj.getClass())
           return false;
        Point other = (Point) obj;
        if (x != other.x)
           return false;
        if (y != other.y)
           return false;
        return true;
   }

}