集合的框架(之一)

集合的含义:

集合是一个可变的容器,可以随时向集合中添加元素,也可以随时从集合中删除元素。另外,集合还提供了若干个用来操作集合中数据的方法。集合里的数据,我们称之为元素(elements);集合只能用来存储引用类型的数据不能存储八大基本数据类型的数据

泛型

Java SE 5.0 以后,可以使用新特性”泛型”,用来指定要存放在集合中的对象类型。避免了强制转换的麻烦。

public class Person<T> {
    private T idCard;

    public Person(T idCard) {
        this.idCard = idCard;
    }
 public static void main(String[] args) {
    Person person = new Person<String>("1001");

}
/**
 * 当一个子类继承带有泛型的父类时,一般情况下要给泛型参数赋值具体类名
 */
Class Student extends Person<Integer>{
    public Student(Integer idcard){
        super(idcard);
}

class Teacher<E> extends Person<E>{
       public Teacher(E idcard){
        super (idcard);
}

class Persident extends Person{

    public Presidert(Object idCard){
        super (idcard);
}
}
}



}



}
泛型接口

Public interface MyComparable<T,M>{
 public int mycompare(T o1, M o2);

    public static void main(String[] args) {
        Employee[] employees = new Employee[3];
        employees[0] = new Employee("John Doe", 23);
        employees[1] = new Employee("Bane Doe", 33);
        employees[2] = new Employee("Yane Doe", 18);
Comparator c = new Comparator<Employee>(){
public int compara(Employee o1 ,Employee o2){
        return o1.mycompare(o1,o2);
}
};
Arrays.sort(employees,c);
System.out.println(Arrays.toString(employees));
}

//子类实现接口:   通常子类要给泛型接口的泛型参数赋值具体类型名


class Employee implements MyComparable<Employee, Employee> {
    String name;
    int age;
    public Employee(String name ,int age){
        this.name = name;
        this.age = age;
    };
    //在我们自己定义的方法,来实现比较规则
    public int mycompare(Employee o1, Employee o2) {
        return o2.age - o1.age;
    }
    @Override
    public String toString(){
        return name + " " + age;
    }



}
泛型方法:泛型应用在方法上, 位置位于返回值类型的前面
案例演示:定义一个工具类,用于比较两个对象长得是否一样。
public class MyUtil{

public static  <T> boolean equals(T t1,T t2){
    return t1.equals(t2);
}
public class MyUtil{
    //工具类
    public static <T> boolean equals(T t1,T t2){
        return t1.equals(t2);
    }

    public static void main(String[] args) {
        Cat c1 = new Cat("十八八");
        Cat c2 = new Cat("十八八");
        //泛型方法在调用期间,不需要指定具体类型,只需要传入具体对象, 编译器会自动推断对象的类型
        //泛型方法调用期间,并没有给泛型参数赋值。下面的案例是c1给t1,c2给t2赋值,没有给T赋值。
        boolean equals = MyUtil.equals(c1, c2);
        System.out.println(equals);
    }
}
class Cat{
    //自定义的类都应该重写equals(),toString()等方法
    String name;
    public Cat(String name){
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Cat cat = (Cat) o;
        return Objects.equals(name, cat.name);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(name);
    }
}


}
泛型通配符: ?   用于表名不关心调用时的具体类型。
public class MyUtil {
    /**
     * 将集合元素打印到控制台上
     */
    public static void print(List<?> lists){
        for (int i = 0; i < lists.size(); i++) {
            System.out.println(lists.get(i));
        }
    }

    /**
     * 上边界的定义: <? extends 具体类名>
     *          具体使用的时候,可以是上边界的任何子类型或者是本类型
     * @param list
     */
    public static void print2(List<? extends Number> list){
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
    /**
     * 下边界的定义:<? super 具体类名>
     *          具体使用的时候,可以是下边界的任何父类型或者本类型
     * @param
     */
    public static void print3(List<? super Integer> list){
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }




    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<Integer>();
        nums.add(1);
        nums.add(2);
        nums.add(3);
        MyUtil.print(nums);

        List<Long> ns = new ArrayList<Long>();
        ns.add(1L);
        ns.add(2L);
        ns.add(3L);
        MyUtil.print(ns);

        //上边界的测试:
        print2(new ArrayList<Long>());
        print2(new ArrayList<Number>());
        //print2(new ArrayList<Object>());  最高到达Number类型

        //下边界的测试:
        print3(new ArrayList<Integer>());
        print3(new ArrayList<Number>());
        print3(new ArrayList<Object>());
        //print3(new ArrayList<Long>());   Long和Integer没有关系。
    }
}

集合与数组

  1. 数组是定长的容器,一旦实例化完成,长度不能改变。集合是变长的,可以随时的进行增删操作。

  2. 数组中可以存储基本数据类型和引用数据类型的元素,集合中只能存储引用数据类型的元素。

  3. 数组的操作比较单一,只能通过下标进行访问。集合中提供了若干个方便对元素进行操作的方法

  4. 在存储引用类型时,集合与数组,存储的其实都是==对象的地址==

集合框架体系图

Collection接口

含义:Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义了他们三个子接口的共同方法。既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。作为父接口,其子类集合的对象,存储元素的特点,可能是无序的,也可能是有序的,因此在父接口中并没有定义通过下标获取元素的方法功能。

常用方法:

public class CollectionDemo {
    public static void main(String[] args) {
        //使用多态的向上造型创建一个子类型对象
        Collection<String> c1 = new ArrayList<>();
        //1. E add(E e)  向集合中添加元素
        c1.add("A");
        c1.add("B");
        c1.add("C");
        //2. boolean isEmpty()
        boolean empty = c1.isEmpty();
        System.out.println("empty: " + empty);
        //3. int  size(): 返回的是集合元素的个数
        System.out.println(c1.size());
        //4. String toString()
        System.out.println(c1);
        Collection<String> c2 = new ArrayList<>();
        c2.add("B");
        c2.add("C");
        c2.add("D");
        //5. addAll(Collection c)
        c1.addAll(c2);
        System.out.println(c1);
        /*
         * 6. boolean contains(Object o):
         *    查看是否包含字符串 "B"
         */
        boolean b = c1.contains("B");
        System.out.println("是否包含字符串B :"+b);
        /*
         * 7. boolean containsAll(Collection c)
         *   查看c1是否包含c2
         */
        boolean b1 = c1.containsAll(c2);
        System.out.println("c1集合是否包含c2集合:"+b1);
        /*
         * 8. boolean  equals(Object o)
         *    测试: 创建一个新的集合c3  添加元素 "A" "B" "C" "B","D","D"
         *    判断两个集合是否相同
         */
        Collection<String> c3 = new ArrayList<>();
        c3.add("A");
        c3.add("B");
        c3.add("C");
        c3.add("B");
        c3.add("C");
        c3.add("D");
        System.out.println("c1和c3相同吗?  :" + c1.equals(c3));

        /** 9.  boolean  remove(Object o)
         *     移除c1集合里的元素B,并查看剩下的元素       */
        boolean d = c1.remove("B");
        System.out.println(" 移除元素B :" + d);
        System.out.println(c1);

        /**  10.  boolean  removeAll(Collection<?> c)
         *       解析: 从集合中删除另一个集合c中所具有的元素。
         *
         *      新建一个集合c4,  添加元素"B","C"
         *      测试c1移除子集c4                        */
        Collection<String> c4 = new ArrayList<>();
        c4.add("B");
        c4.add("C");
        c1.removeAll(c4);
        System.out.println(c1);

        /**   11.  boolean retainAll(Collection c)
         *      测试:向c1里添加"E","F","G",  然后保留子集c5,  c5里的元素有"A","E"   */
        c1.add("E");
        c1.add("F");
        c1.add("G");
        Collection<String> c5 = new ArrayList<>();
        c5.add("A");
        c5.add("E");
        c5.add("H");
        c1.retainAll(c5);
        System.out.println(c1);

        /** 12.  void clear():
         *      测试:清空c1                   */
        c1.clear();
        System.out.println(c1);
        System.out.println(c1.size());
    }
}

集合的迭代

1. 集合的迭代,就是指集合的遍历操作。2. 几乎所有的集合子类型都实现了迭代接口Iterable.

迭代接口提供的方法: 

boolean hasNext()     可以形象的认为有指针,指针的最初位置在第一个元素的前面。

E next()   用于返回指针指向的那个元素,然后指针向后移动,为下一次的判断。

E remove() 用于删除指针指向的那个元素。
在使用迭代器时,不可以调用集合自己的remove方法。
public class CollectionDemo02 {
    public static void main(String[] args) {

Collection<Integer> c1 = new ArrayList();

        c1.add(1);
        c1.add(2);
        c1.add(3);
        c1.add(4);
        c1.add(5);

    for(Integer i: c1){
         System.out.print(i+"  ");
}
System.out.println();
//使用迭代器iterator进行遍历

Iterator<Integer> it = c1.iterator();
while(it.hasNext()){
    Integer a = it.next;
       System.out.println("a:"+a);
}

}


}

迭代器的源码解析

三个成员变量:
*    cursor:  记录下一次要返回的元素的下标
*    lastRet:  记录上一次刚刚返回的元素的下标
*    expectedModCount:  预计的修改次数。 默认为集合的长度 ,与modCount的值息息相关
*                        注意:集合在调用add(E e)方法添加元素时,modCount++。
*
*    hasNext():    return  cursor!=size   : 当光标的值为集合长度时,没有下一个元素了。
*    next():
*        1. 检查 expectedModCount和modCount 是否一样,如果不一致,就抛异常。
*        2. 光标的值先赋值给lastRet。 相当于指针后移。 光标的值+1,为下一次的hasNext()做准备工作
*           新的lastRet的值就是指针指向的元素,也就是刚刚取出来的元素
*    remove():
*        1.  检查 expectedModCount和modCount 是否一样,如果不一致,就抛异常。
*        2.  调用ArrayList的  E remove(int index) 做真正的删除元素操作。
*            而E remove(int index)里面调用了System.arraycopy()方法,
*            从指定的index+1处,向前移动一位,以此形式做删除工作。
*
*            index的值是lastRet赋值的。
*
*            因为后续的元素向前移动了,因此cursor也要向前移动一次, 即cursor=lastRet.
*            如果不向前移动,会漏掉元素。 即 index+1这个位置上的元素,就会被漏掉。
*
*            最重要的是:  remove(int index)里面进行了modCount++操作。
*            但是 迭代器的remove里,进行重新赋值expectedModCount = modCount;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值