Java学习笔记之集合

来源:互联网 发布:淘宝裙子 编辑:程序博客网 时间:2024/05/14 11:33

5.集合

集合
=====================================
  * 用来存放一组数据的数据结构

  * java.util 包
  ------------------------
      Collection 接口
         |- List 接口
              |- ArrayList
              |- LinkedList
         |- Set 接口
              |- HashSet
              |- TreeSet

      Map 接口
        |- HashMap
        |- TreeMap

      Collections 工具类
      Iterator 接口








java.util.LinkedList
==============================================
  * 双向链表
  * 两端效率高

  创建对象
  ---------------------------------------
    LinkedList list = new LinkedList();

  方法
  ---------------------------------------
    add(数据)                添加数据
    add(int index, 数据)    在指定位置插入数据
    addFirst(数据) 
    addLast(数据)
    getFirst()
    getLast()
    removeFirst()
    removeLast()   
    FIFO 操作 First In First Out,队列Queue操作
        offer(数据)    - addLast
        peek()        - getFirst
        poll()        - removeFist   
    LIFO 操作 Last In Fisrt Out,栈Stack操作
        push()        - addFirst
        pop()          - removeFist
    get(int index)    - 获得指定位置的值
    contains(数据)      - 判断列表中是否存在与指定数据相等(equals)的值
    set(int index, 数据)      - 将指定位置设置为新的值
    size()            - 获得列表中数据的数量
    remove(int index)  - 移除指定位置的元素,并返回被移除的数据
    remove(数据)        - 移除与指定数据相等的数据
    clear()            - 清空
    iterator()        - 获得迭代器实例








java.util.ArrayList
==========================================
  * 内部使用数组存放数据
  * 访问任意位置效率高
  * 添加、删除数据,效率可能会降低

  * ArrayList  vs  LinkedList

      *) 如果只在两端操作数据,选择LinkedList


  创建对象
  --------------------------------------
    1.ArrayList list = new ArrayList();

        内部数组容量 10

    2.ArrayList list = new ArrayList(100);

        内部数组容量 100
        加大初始容量,可以减少数组创建次数

  方法
  --------------------------------------
    * 与 LinkedList 相同,
      但没有两端操作数据的方法




提问:
1. 请详细描述ArrayList与LinkedList在存储数据时的区别
ArrayList:以数组的结构存储数据,各数据在ArrayList中是序列的,具有读取数据快、修改数据慢的特点
LinkedList:以链表的结构存储数据,具有读取数据慢、修改数据快的特点






java.util.HashMap
===========================================
  * 哈希表、散列表
  * 存放“键值对”数据
  * 快速查找数据

  * 键:

      *) 不重复
      *) 无序

  创建对象
  --------------------------------------
    HashMap map = new HashMap();

  方法
  --------------------------------------
    put(k, v)   放入键值对数据
    get(k)      用键获得对应的值
    remove(k)   移除指定的键和它的值
    containsKey(key)    是否包含指定的键
    containsValue(value)是否包含指定的值
    size()              有多少对数据
    clear()              清空

    keySet()            获得一个 Set 类型集合,包含所有的键
    entrySet()          获得一个 Set 类型结合,包含所有 Entry
    values()            获得集合,包含所有的值


  哈希算法、散列算法
  ------------------------------------
    放数据
    -----------------------------
      1.key.hashCode() 获得键的哈希值
      2.用哈希值计算产生下标值 index
      3.创建 Entry 对象封装键值对
      3.5.如果达到一定负载率,数组容量翻倍
      4.将 Entry 对象放入 index 位置
          4.1.index是空位置,直接放入
          4.2.index位置已经存在数据
              4.2.1.依次用equals()比较每个键是否相等
                    4.2.1.1.找到相等的,覆盖值
                    4.2.1.2.找不到相等,链表连在一起

    取数据
    ----------------------------------
      1.key.hashCode() 获得键的哈希值
      2.用哈希值计算产生下标值 index
      3.依次与每个键用equals()比较是否相等
          3.1.找到相等键,取出它的值
          3.2.找不到相等的键,返回null值











java.util.TreeMap
=========================================
  * 红黑树
  * 用来快速查找数据

  * 键:
      *) 不重复
      *) 从小到大

      *) 键比较大小,两种方式
            1) 实现 Comparable 接口
            2) TreeMap 外接比较器 Comparator

  创建对象
  -------------------------------------
    1.TreeMap map = new TreeMap();

    2.TreeMap map = new TreeMap(比较器);

  方法
  -------------------------------------
    *)与 HashMap 相同










java.util.Set 接口
    |- HashSet
    |- TreeSet
================================================
  * Set  不重复的数据集
  * HashSet

      *) 内部封装一个 HashMap 对象,
         数据作为键,放入 HashMap
      *) 不重复、无序

  * TreeSet

      *) 内部封装一个 TreeMap 对象,
         数据作为键,放入 TreeMap
      *) 不重复、有序

      *) TreeSet 创建对象:

          TreeSet set = new TreeSet();

          TreeSet set = new TreeSet(比较器);

  方法
  ----------------------------------
    add(数据)
    remove(数据)
    size()
    contains(数据)
    clear()
    iterator()


2. 请详细描述如何将自定义的Student类存储在一个TreeSet集合中
Set集合都是散列的,例如以下代码段:
Set<String> strings = new HashSet<String>();
strings.add("hello_1");
strings.add("hello_2");
strings.add("hello_3");
strings.add("hello_4");
strings.add("hello_5");
如果输出以上集合,则输出的顺序与添加数据的顺序没有关系,即输出的顺序可以理解为随机的顺序。
遍历Set的方式1:增强for循环/foreach语法
for(String str : strings) {
  System.out.println(str);
}
遍历Set的方式2:迭代器Iterator
Iterator<String> it = strings.iterator();
while(it.hasNext()) {
  it.next();
}
Set集合的中的各元素是不可重复的!例如以下代码段中:
Set<String> strings = new HashSet<String>();
strings.add("hello_1");
strings.add("hello_2");
strings.add("hello_3");
strings.add("hello_2");
strings.add("hello_1");
尽管添加了5个数据,但是在集合中只会有3个数据,相同的2个"hello_1"和"hello_2"各存在1个数据。
假设创建Student类:
public class Student {
  public String name;
  public int age;
}
尝试向集合中添加数据:
Set<Student> students = new HashSet<Student>();
Student stu1 = new Student();
stu1.name = "Mike";
stu1.age = 18;
students.add(stu1);
Student stu2 = new Student();
stu2.name = "Mike";
stu2.age = 18;
students.add(stu2);
如果运行以上代码,则集合中存在2个Student对象,因为Set集合判断数据是否相同的标准是:2个对象使用equals()对比的结果为true,且2个对象的hashCode()方法的返回值是相同的。
如果希望以上代码执行后,Set集合中只有1个对象,则应该修改Student类:
public class Student {
  public String name;
  public int age;
 
  @Override
  public boolean equals(Object other) {
    // 制定规则:姓名、年龄相同,则返回true
    if(other instanceof Student) {
      Student stu = (Student) other;
      if((this.name.equals(stu.name) == true) && (this.age == stu.age)) {
        return true;
      }
    }
    return false;
  }
 
  @Override
  public int hashCode() {
    // 制定规则:姓名、年龄相同,则计算得到相同的int值
    return this.name.hashCode() + age;
  }
}
TreeSet是一种可以自动排序的Set集合,添加到TreeSet中的各对象会按照字典排序法顺序排列,例如:
Set<String> strings = new TreeSet<String>();
strings.add("hello_1");
strings.add("hello_5");
strings.add("hello_3");
strings.add("hello_2");
strings.add("hello_4");
如果输出以上Set集合的内容,则是:
hello_1
hello_2
hello_3
hello_4
hello_5
由于TreeSet会对存储的数据进行自动排序,则要求TreeSet中的数据类型实现Comparable接口,例如:
public class Student implements Comparable<Student> {
  public String name;
  public int age;
 
  @Override
  public int compareTo(Student another) {
    return this.name.compareTo(another.name);
  }
 
  @Override
  public boolean equals(Object other) {
    // 制定规则:姓名、年龄相同,则返回true
    if(other instanceof Student) {
      Student stu = (Student) other;
      if((this.name.equals(stu.name) == true) && (this.age == stu.age)) {
        return true;
      }
    }
    return false;
  }
 
  @Override
  public int hashCode() {
    // 制定规则:姓名、年龄相同,则计算得到相同的int值
    return this.name.hashCode() + age;
  }
}







java.util.Iterator 接口
============================================
  * 迭代器父接口

  方法
  ---------------------------------
    hasNext()
    next()

    remove() 
        移除刚刚取出的数据








java.util.Collections
=============================================
  * 集合工具类

  方法
  -------------------------------------
    addAll(Collection,值1,值2,值3...)

        向指定集合,加入多个数据

    binarySearch(List, 数据)

        二分法查找,
        List 集合中的数据,必须是从小到大
        返回数据的下标位置,找不到返回无意义值

    fill(List, 数据)

        将现有数据,全部替换为指定的数据

    max(Collection)
    max(Collection, Comparator) 外接比较器
    min(Collection)
    min(Collection, Comparator) 外接比较器

    reverse(List)

        翻转

    shuffle(List)

        打乱

    sort(List)
    sort(List, Comparator) 外接比较器

        排序

    swap(List list, int i, int j)

        i、j位置交换












for-each 循环
==========================================
  * 数组下标遍历、集合迭代遍历的语法简化

  * 数组遍历

        for(int i=0;i<a.length;i++) {
            String s = a[i];
            //处理s
        }

        --------

        for(String s : a) {
            //处理s
        }

  * 集合遍历

        for(Interator<String> it = list.iterator(); it.hasNext(); ) {
            String s = it.next();
            //处理s
        }

        --------

        for(String s : list) {
            //处理s
        }













可变长参数
==========================================
  * 数组参数的语法简化

      void f(int[] a) {
        //处理数组a
      }

      f(new int[]{2,3,6,1,3,5});
      f(new int[]{2,1});
      f(new int[]{})

      --------

      void f(int... a) {
        //处理数组a
      }

      f(2,3,6,1,3,5);
      f(2,1);
      f();










枚举 enumeration
==========================================
  * 一组固定选项
  * 代替整数代码选项,
    提供类型安全的选项

  * 定义枚举用 enum 关键字代替 class 关键字

      public enum WeaponType {
          COLD, HEAT, NUCLEAR
      }

      其中的选项,本质是WeaponType类型的实例
          WeaponType COLD=new WeaponType();














泛型
==========================================
  * 参数化的数据类型

        class A<T> {
            T t;

            void f(T t) {

            }

            T f() {

            }
        }

0 0