java基础(7)集合与泛型

1 collection集合

集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map。

Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法和举例如下:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

/*
    java.util.Collection接口
        所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法
        任意的单列集合都可以使用Collection接口中的方法


    共性的方法:
      public boolean add(E e):  把给定的对象添加到当前集合中 。
      public void clear() :清空集合中所有的元素。
      public boolean remove(E e): 把给定的对象在当前集合中删除。
      public boolean contains(E e): 判断当前集合中是否包含给定的对象。
      public boolean isEmpty(): 判断当前集合是否为空。
      public int size(): 返回集合中元素的个数。
      public Object[] toArray(): 把集合中的元素,存储到数组中。
 */
public class Demo01Collection {
    public static void main(String[] args) {
        //创建集合对象,可以使用多态
        Collection<String> coll = new ArrayList<>();
        Collection<String> coll = new HashSet<>();
        System.out.println(coll);//重写了toString方法  []

        /*
            public boolean add(E e):  把给定的对象添加到当前集合中 。
            返回值是一个boolean值,一般都返回true,所以可以不用接收
         */
        boolean b1 = coll.add("张三");
        System.out.println("b1:"+b1);//b1:true
        System.out.println(coll);//[张三]
        coll.add("李四");
        coll.add("李四");
        coll.add("赵六");
        coll.add("田七");
        System.out.println(coll);//[张三, 李四, 赵六, 田七]

        /*
            public boolean remove(E e): 把给定的对象在当前集合中删除。
            返回值是一个boolean值,集合中存在元素,删除元素,返回true
                                集合中不存在元素,删除失败,返回false
         */
        boolean b2 = coll.remove("赵六");
        System.out.println("b2:"+b2);//b2:true

        boolean b3 = coll.remove("赵四");
        System.out.println("b3:"+b3);//b3:false
        System.out.println(coll);//[张三, 李四, 田七]

        /*
            public boolean contains(E e): 判断当前集合中是否包含给定的对象。
            包含返回true
            不包含返回false
         */
        boolean b4 = coll.contains("李四");
        System.out.println("b4:"+b4);//b4:true

        boolean b5 = coll.contains("赵四");
        System.out.println("b5:"+b5);//b5:false

        //public boolean isEmpty(): 判断当前集合是否为空。 集合为空返回true,集合不为空返回false
        boolean b6 = coll.isEmpty();
        System.out.println("b6:"+b6);//b6:false

        //public int size(): 返回集合中元素的个数。
        int size = coll.size();
        System.out.println("size:"+size);//size:3

        //public Object[] toArray(): 把集合中的元素,存储到数组中。
        Object[] arr = coll.toArray();
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);//张三 李四 田七
        }

        //public void clear() :清空集合中所有的元素。但是不删除集合,集合还存在
        coll.clear();
        System.out.println(coll);//[]
        System.out.println(coll.isEmpty());//true
    }
}

2 Iterator迭代器

2.1 Iterator接口

迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。

Iterator接口的常用方法如下:

  • public E next():返回迭代的下一个元素。
  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。

迭代器的代码实现:

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

/*
    java.util.Iterator接口:迭代器(对集合进行遍历)
    有两个常用的方法
        boolean hasNext() 如果仍有元素可以迭代,则返回 true。
            判断集合中还有没有下一个元素,有就返回true,没有就返回false
        E next() 返回迭代的下一个元素。
            取出集合中的下一个元素
    Iterator迭代器,是一个接口,我们无法直接使用,需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊
    Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象
        Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。

    迭代器的使用步骤:
        1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
        2.使用Iterator接口中的方法hasNext判断还有没有下一个元素
        3.使用Iterator接口中的方法next取出集合中的下一个元素
 */
public class Demo01Iterator {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection<String> coll = new ArrayList<>();
        //往集合中添加元素
        coll.add("姚明");
        coll.add("科比");
        coll.add("麦迪");
        coll.add("詹姆斯");
        coll.add("艾弗森");

        /*
            1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
            注意:
                Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
         */
          //1. 多态  接口            实现类对象
        Iterator<String> it = coll.iterator();
      //2.使用Iterator接口中的方法hasNext判断还有没有下一个元素
        boolean b = it.hasNext();
        System.out.println(b);//true
          //3.使用Iterator接口中的方法next取出集合中的下一个元素
        String s = it.next();
        System.out.println(s);//姚明

        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);

        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);

        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);

        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);

        b = it.hasNext();
        System.out.println(b);//没有元素,返回false
        s = it.next();//没有元素,再取出元素会抛出NoSuchElementException没有元素异常
        System.out.println(s);*/


 /*
            发现使用迭代器取出集合中元素的代码,是一个重复的过程
            所以可以使用循环优化
            不知道集合中有多少元素,使用while循环
            循环结束的条件,hasNext方法返回false
         */
        while(it.hasNext()){
            String e = it.next();
            System.out.println(e);
        }
System.out.println("----------------------"); for(Iterator<String> it2 = coll.iterator();it2.hasNext();){ String e = it2.next(); System.out.println(e); }
    }
}

迭代器的实现原理:

3 泛型

3.1 泛型的概念:

3.2 泛型的定义和使用

3.2.1 定义和使用含有泛型的类

//定义一个泛型
public class GenericClass<g> {//g随便改成一个字母都行,主要是尖括号
    private g name;

    public g getName() {
        return name;
    }

    public void setName(g name) {
        this.name = name;
    }
}

//测试
public class GenericClassTest {
    public static void main(String[] args) {
        GenericClass<Integer> gc = new GenericClass<>();//创建对象的时候才确定泛型的实际类型,这里使用的是Integer
        gc.setName(1);
        System.out.println(gc.getName());

        GenericClass<String> gc1 = new GenericClass<>();//也可以使用String类型
        gc1.setName("小明明");
        System.out.println(gc1.getName());
    }
}

3.2.2 定义和使用含有泛型的方法

//创建一个含有泛型方法的类
public class GenericMethod {
    public <e> void gmMethod(e ele){
        System.out.println(ele);
}

    public static <m> void staticGm(m mm){
        System.out.println(mm);
    }
}
//测试 public class GenericMethodTest { public static void main(String[] args) { GenericMethod method1 = new GenericMethod(); method1.gmMethod(1); method1.gmMethod("aaaaaaa"); method1.gmMethod(true); GenericMethod method2 = new GenericMethod(); method2.staticGm(222); GenericMethod.staticGm("静态方法建议用类名.静态方法名调用"); } }

3.2.3 定义和使用含有泛型的接口

//创建一个含有泛型的接口
public interface GenericInterface<e> {
    void method(e m);
}

//第一个方法:创建实现类的时候就指明实现类的类型
public class GenericInterfaceImp implements GenericInterface<String > {

    @Override
    public void method(String  m) {
        System.out.println("重写了抽象类的方法");
        System.out.println(m);
    }
}

//第二个方法:创建实现类的时候,泛型跟着接口的泛型走,创建对象的时候才指明泛型的具体类型
public class GenericInterfaceImp2<e> implements GenericInterface<e> {//注意这两个地方都需要加尖括号<>,而且里面的类型与接口的泛型一致
    @Override
    public void method(e m) {
        System.out.println(m);
    }
}

//测试
public class GenericInterfaceImpTest {
    public static void main(String[] args) {
        GenericInterfaceImp imp = new GenericInterfaceImp();
        imp.method("传递的参数就是这个" );

        GenericInterfaceImp2<Integer> imp2 = new GenericInterfaceImp2<Integer>();//注意要在这里创建时指明泛型的具体类型,
                                                                                 //否则下面的方法调用的参数会是Object类型
        imp2.method(1111);
    }
}

3.2.4 泛型的通配符

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

public class GenericInterfaceImpTest {
    public static void main(String[] args) {
        GenericInterfaceImp imp = new GenericInterfaceImp();
        imp.method("传递的参数就是这个" );

        GenericInterfaceImp2<Integer> imp2 = new GenericInterfaceImp2<Integer>();
        imp2.method(1111);

        System.out.println("====测试通配符====");
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("aaa");
        list1.add("bbb");
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(123);
        list2.add(456);
        printArrayList(list1);
        printArrayList(list2);
    }

    public static void printArrayList(ArrayList<?> list){

        //Iterator iterator = new Iterator();//Iterator是一个接口,不能直接new,
        Iterator<?> it = list.iterator();//集合list是什么类型,迭代器就是什么类型。测试中发现,问号不写也不会报错
        //Iterator it = list.iterator();//需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊:
                 // Collection对象(可以换成具体的如ArrayList对象,也可以就用Collection对象)有一个方法,叫iterator(),这个方法返回的就是迭代器的实现类对象
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }
}

//Output

重写了抽象类的方法
传递的参数就是这个
1111
====测试通配符====
aaa
bbb
123
456

3 list集合

3.1 List接口概述

Collection中的常用几个子类包括( java.util.List 集合、java.util.Set 集合)

List接口特点:
1. 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、
22、33的顺序完成的)。
2. 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
3. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

3.2 ArrayList集合

java.util.ArrayList 集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为
查询数据、遍历数据,所以ArrayList 是最常用的集合。

 ArrayList底层是数组结构(所以名字带Array)。

ArrayList不是同步的,多线程的(快)。

1.0版本中的Vector是同步的,单线程(慢)。

1.2以后,Vector被ArrayList代替。

3.2 LinkedList集合

 LinkedList是双向链表。由于底层是一个链表结构:元素增删快,查找慢。

4  Set接口

Set 接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。

没有索引,没有带索引的方法,不能使用普通的带for循环的遍历。

tips:Set集合取出元素的方式可以采用:迭代器、增强for。

4.1 HashSet集合介绍

java.util.HashSet 是Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序
不一致)。java.util.HashSet 底层的实现其实是一个java.util.HashMap 支持。

4.1.1 哈希值

/*
    哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)
    在Object类有一个方法,可以获取对象的哈希值
    int hashCode() 返回该对象的哈希码值。
    hashCode方法的源码:
        public native int hashCode();
        native:代表该方法调用的是本地操作系统的方法
 */
public class Demo01HashCode {
    public static void main(String[] args) {
        //Person类继承了Object类,所以可以使用Object类的hashCode方法
        Person p1 = new Person();
        int h1 = p1.hashCode();
        System.out.println(h1);//1967205423  

        Person p2 = new Person();
        int h2 = p2.hashCode();
        System.out.println(h2);//42121758 

        /*
            toString方法的源码:
                return getClass().getName() + "@" + Integer.toHexString(hashCode());
         */
        System.out.println(p1);//@75412c2f
        System.out.println(p2);//@282ba1e
        System.out.println(p1==p2);//false

        /*
            String类的哈希值
                String类重写了Obejct类的hashCode方法
         */
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1.hashCode());//96354
        System.out.println(s2.hashCode());//96354

        System.out.println("重地".hashCode());//1179395 巧合
        System.out.println("通话".hashCode());//1179395
    }
}

4.1.2 HashSet集合存储数据的结构(哈希表)

Set集合(如java.util.HashSet 、java.util.LinkedHashSet 这两个集合)不允许存储重复元素的原理:

 

猜你喜欢

转载自www.cnblogs.com/JohnTeslaaa/p/10296843.html