黑马程序员JAVA学习第五节

本节主要内容是 Collection集合,List 集合,数据结构补充知识,Set集合,泛型,对应视频220-256.

Collection集合

1.集合体系结构

java 集合拼接 java集合视频教程_java 集合拼接

2.创建Collection集合的对象:

JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现

多态的方式,具体的实现类ArrayList

3.Collection集合的常用方法

boolean add(E e)            添加元素
boolean remove(Object o) 从集合中移除指定的元素
void clear() 清空集合中的元素
boolean contains(Object o) 判断集合中是否存在指定的元素
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中元素的个数

4.Collection集合的遍历

迭代器的介绍:
迭代器,集合的专用遍历方式
Iterator<E>iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
迭代器是通过集合的 iterator()方法得到的,所以我们说它是依赖于集合而存在的

常用方法:

E next():返回迭代中的下一个元素

 boolean hasNext(): 如果迭代具有更多元素则返回true

//创建集合对象
    Collection<String> c = new ArrayList<>();
    //添加元素
    c.add("hello");
    //Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
    Iterator<String> it = c.iterator();
    //用while循环改进元素的判断和获取
    while (it.hasNext()) {
      String s = it.next();
      System.out.println(s);
   }

List 集合(继承自Collection,儿子是ArrayList)

1.概述
有序集合 (也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
与 Set集合不同,列表通常允许重复的元素

2.List 集合特点;有索引;可以存储重复元素;元素存取有序。

3.List集合的特有方法
void add(int index,E element) 在此集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素

4.List集合的两种遍历方式:

遍历集合时修改其中的元素用for循环

//迭代器方式
    Iterator<Student> it = list.iterator();
    while (it.hasNext()) {
      Student s = it.next();
      System.out.println(s.getName() + "," + s.getAge());
   }
   
    System.out.println("--------");
    //for循环方式
    for(int i=0; i<list.size(); i++) {
      Student s = list.get(i);
      System.out.println(s.getName() + "," + s.getAge());
   }

5.列表迭代器ListIterator(继承自Iterator)

1)介绍:通过 List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
用于允许程序员沿任一方向遍历的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

2)遍历并添加元素:

//获取列表迭代器
    ListIterator<String> lit = list.listIterator();
    while (lit.hasNext()) {
      String s = lit.next();
      if(s.equals("world")) {
        lit.add("javaee");
     }
   }

6.增强for:

内部原理是一个Iterator迭代器

格式:

for (元素数据类型 变量名 : 数组/集合对象名) {
  循环体;

}
   int[] arr = {1,2,3,4,5};
     for(int i : arr) {
       System.out.println(i);
    }

7.List集合子类的特点:

ArrayList 集合
底层是数组结构实现,查询快、增删慢
LinkedList 集合
底层是链表结构实现,查询慢、增删快

8.LinkedList集合的特有功能

java 集合拼接 java集合视频教程_java_02

数据结构

1.栈和队列

栈结构:先进后出
队列结构:先进先出

2.数组结构:查询快、增删慢
队列结构:查询慢、增删快

java 集合拼接 java集合视频教程_列表_03

Set集合

1.Set集合概述和特点

       Set 集合的特点
       1)元素存取无序
       2)没有索引、只能通过迭代器或增强 for循环遍历
       3)不能存储重复元素 

Set<String> set = new HashSet<String>();

2.哈希值

1)哈希值简介
   是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
2)如何获取哈希值
   Object类中的public int hashCode():返回对象的哈希码值
3)哈希值的特点
   同一个对象多次调用 hashCode()方法返回的哈希值是相同的
   默认情况下,不同对象的哈希值是不同的。而重写 hashCode()方法,可以实现让不同对象的哈希     值相同
4)获取哈希值的代码

System.out.println("hello".hashCode()); //99162322
    System.out.println("world".hashCode()); //113318802

3.HashSet集合概述和特点

1)HashSet 集合的特点
   底层数据结构是哈希表;
   对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致;
   没有带索引的方法,所以不能使用普通 for循环遍历;
   由于是 Set集合,所以是不包含重复元素的集合;
4.HashSet集合保证元素唯一性源码分析

java 集合拼接 java集合视频教程_迭代器_04

5.常见数据结构之哈希表

哈希表底层采用数组+链表实现,默认初始容量是16,先对哈希值取余,然后结合上一点进行存储

java 集合拼接 java集合视频教程_java_05

6.对象重写Hashcode

alt+insert,找到hashcode和equal;

7.LinkedHashSet集合概述和特点

1)LinkedHashSet 集合特点
   哈希表和链表实现的 Set接口,具有可预测的迭代次序;
   由链表保证元素有序,也就是说元素的存储和取出顺序是一致的;
   由哈希表保证元素唯一,也就是说没有重复的元素;

2)LinkedHashSet 集合基本使用

LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();

8. TreeSet集合概述和特点

1)TreeSet 集合概述;
       元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法;
             TreeSet() :根据其元素的自然排序进行排序;
             TreeSet(Comparator comparator) :根据指定的比较器进行排序;
        没有带索引的方法,所以不能使用普通 for循环遍历;
        由于是 Set集合,所以不包含重复元素的集合;

2)使用方法

TreeSet<Integer> ts = new TreeSet<Integer>();

9.自然排序Comparable的使用

public class Student implements Comparable<Student> {
  @Override
  public int compareTo(Student s) {

    //按照年龄从小到大排序
   int num = this.age - s.age;
//    int num = s.age - this.age;
    //年龄相同时,按照姓名的字母顺序排序
   int num2 = num==0?this.name.compareTo(s.name):num;
    return num2;
 }
}

public class TreeSetDemo02 {
  public static void main(String[] args) {
    //创建集合对象
    TreeSet<Student> ts = new TreeSet<Student>();
    //创建学生对象
    Student s1 = new Student("xishi", 29);
    Student s2 = new Student("wangzhaojun", 28);
    //把学生添加到集合
    ts.add(s1);
    ts.add(s2);
    //遍历集合
    for (Student s : ts) {
      System.out.println(s.getName() + "," + s.getAge());
   }
 }
}

10.比较器排序Comparator的使用

//创建集合对象
    TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
      @Override
      public int compare(Student s1, Student s2) {
        //this.age - s.age
        //s1,s2
        int num = s1.getAge() - s2.getAge();
        int num2 = num == 0 ? s1.getName().compareTo(s2.getName()): num;
        return num2;
     }
   });

两种方法区别是一种是实现的Comparable接口,另一种是创建集合对象时添加的内部类(student不用implements,正常写就行)。

泛型

1.泛型概述和好处

1)它的本质是参数化类型,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口。

2)泛型定义格式
   < 类型>:指定一种类型的格式。这里的类型可以看成是形参
   < 类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
   将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
3)泛型的好处
把运行时期的问题提前到了编译期间
避免了强制类型转换

2.泛型类

定义格式:

修饰符 class 类名<类型> { } 
//范例
public class Generic<T>{
 private T t;
  public T getT() {
    return t;
 }
  public void setT(T t) {
    this.t = t;
 }
}
//此处T可以随便写为任意标识,常见的如T,E,K,V等形式的参数常用于表示泛型

3.泛型方法

//修饰符 <类型> 返回值类型 方法名(类型 变量名) { } 
public class Generic {
  public <T> void show(T t) {
    System.out.println(t);
 }
}
public class GenericDemo {
  public static void main(String[] args) {
    Generic g = new Generic();
    g.show("林青霞");
 }
}

4.泛型接口

//修饰符 interface 接口名<类型> { }
//泛型接口
public interface Generic<T> {
  void show(T t);
}
//泛型接口实现类
public class GenericImpl<T> implements Generic<T> {
  @Override
  public void show(T t) {
    System.out.println(t);
 }
}
//测试类
public class GenericDemo {
  public static void main(String[] args) {
    Generic<String> g1 = new GenericImpl<String>();
    g1.show("林青霞");
    Generic<Integer> g2 = new GenericImpl<Integer>();
    g2.show(30);
 }
}

5.类型通配符:

1)类型通配符的作用

为了表示各种泛型 List的父类,可以使用类型通配符
2)类型通配符的分类
       类型通配符: <?>
                   List<?> :表示元素类型未知的List,它的元素可以匹配任何的类型
                    这种带通配符的 List仅表示它是各种泛型List的父类,并不能把元素添加到其中
        类型通配符上限(限定最大): <? extends 类型>
                     List<? extends Number> :它表示的类型是Number或者其子类型
        类型通配符下限(限定最小): <? super 类型>
                      List<? super Number> :它表示的类型是Number或者其父类型

3)基本使用

List<? extends Number> list5 = new ArrayList<Number>();
List<? super Number> list7 = new ArrayList<Object>();

 6.可变参数:

1)可变参数介绍
   可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了

2)可变参数定义格式

   修饰符 返回值类型 方法名(数据类型… 变量名) { } 

3)可变参数的注意事项
       这里的变量其实是一个数组
        如果一个方法有多个参数,包含可变参数,可变参数要放在最后

System.out.println(sum(10,20,30,40,50,60,70,80,90,100));
  public static int sum(int... a) {
    int sum = 0;
    for(int i : a) {
      sum += i;
   }
    return sum;
 }

7.可变参数的使用

1)Arrays 工具类中有一个静态方法:
        public static List asList(T... a):返回由指定数组支持的固定大小的列表
         返回的集合不能做增删操作,可以做修改操作
2)List 接口中有一个静态方法:
         public static List of(E... elements):返回包含任意数量元素的不可变列表
         返回的集合不能做增删改操作
3)Set 接口中有一个静态方法:
          public static Set of(E... elements) :返回一个包含任意数量元素的不可变集合
          在给元素的时候,不能给重复的元素
          返回的集合不能做增删操作,没有修改的方法