集合

  • 集合概念:对象的容器,定义了对多个对象进行操作的常用方法,可实现数组的功能

  • 和数组的区别

    1. 数组长度固定,集合长度不固定

    2. 数组可以存储基本类型和引用类型,集合只能存储引用类型 (装箱和拆箱操作)

  • 位置:java.util.*;

Collection体系集合

 

 

interface Collection:该体系结构的根接口,代表一组对象,成为集合

List接口特点:有序,有下标,元素可重复

Set接口特点:无序,无下标,元素不可重复

Collection父接口
  • 特点:代表一组任意类型的对象,无序,无下标,不可重复

  • 方法:

  1. boolean add(Object obj) //添加一个对象。

  2. boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中。

  3. void clear()//清空此集合中的所有对象。

  4. boolean contains (Object o) //检查此集合中是否包含o对象。

  5. boolean equals(0bject o) //比较此集合是否与指定对象相等。

  6. boolean isEmpty() //判断此集合是否为空。

  7. boolean remove (0bject o) //在此集合中移除o对象。

  8. int size() //返 回此集合中的元素个数。

  9. 0bject[] toArray() //将 此集合转换成数组。

  10. Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。 (遍历集合的方法)

Collection 接口的使用:
//1. 添加元素
      collection.add("苹果");
      collection.add("香蕉");
      collection.add("西瓜");
      collection.add("榴莲");
      System.out.println("元素个数:" + collection.size());
      System.out.println(collection);
//2. 删除元素
      //collection.remove("榴莲");
      //collection.clear();
      //System.out.println("元素个数:" + collection.size());
//3. 遍历元素【重点】
//3.1 增强for循环(不可以使用for循环,因为集合无下标)
      System.out.println("===========3.1 增强for循环==============");
      for (Object object:collection) {
          System.out.println(object);
      }
//3.2 使用迭代器(迭代器专门用来遍历集合的一种方式)
      //hasNext();有没有下一个元素
      //next();获取下一个元素
      //remove();删除当前元素
      System.out.println("===========3.2 使用迭代器==============");
      Iterator it = collection.iterator();
      while (it.hasNext()){
          String next = (String) it.next();
          System.out.println(next);
          //ConcurrentModificationException:并发修改异常
          //不允许使用其他的方法改变集合元素
          //collection.remove(next);
          //但是可以使用迭代器自身的remove()方法
          //it.remove();
      }
      System.out.println("元素个数:"+ collection.size());
//4. 判断
      System.out.println(collection.isEmpty());
      System.out.println(collection.contains("西瓜"));
List子接口

特点:有序,有下标,元素可重复

方法:

  1. void add(int index0bject o) //在index位 置插入对象o

  2. boolean addAll(int index, Collection c) //将一个集合中的元素添加到此集合中的index位置。

  3. 0bject get(int index) //返 回集合中指定位置的元素。

  4. List subList(int fromIndex, int toIndex) //返 回fromIndex和toIndex之间的集合元素。

  5. ListIterator<E> listIterator() 返回此列表元素的列表迭代器(按适当顺序)。

  6. ListIterator<E> listIterator(int index) 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

List 接口的使用
//创建列表
List list = new ArrayList();
//1 添加
list.add("iPhone");
list.add("realme");
list.add(0,"moto");
list.add("xiaomi");
list.add(2,"iqoo");
System.out.println("元素个数:" + list.size());
System.out.println(list.toString());
//2 删除
//list.remove("realme");
//list.remove(0);
// list.clear();
//System.out.println("删除之后元素个数:"+list.size());
//3 遍历
//3.1 for循环遍历
System.out.println("===========for循环遍历============");
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
//3.2 增强for循环遍历
System.out.println("===========增强for循环遍历============");
for (Object object:list) {
    System.out.println(object);
}
//3.3 迭代器遍历
System.out.println("===========Iterator迭代器遍历============");
Iterator it = list.iterator();
while (it.hasNext()){
    System.out.println(it.next());
}
//3.4 列表迭代器遍历,和Iterator区别:ListIterator可以向前或向后遍历,添加 删除 修改元素
System.out.println("===========列表迭代器遍历 从前往后============");
ListIterator lit = list.listIterator();
while (lit.hasNext()){
    System.out.println(lit.next());
}
System.out.println("===========列表迭代器遍历 从后往前============");
while (lit.hasPrevious()){
    System.out.println(lit.previousIndex() + ":" + lit.previous());
}
//4 判断
System.out.println(list.isEmpty());
System.out.println(list.contains("华为"));
//5 获取位置
System.out.println(list.indexOf("realme"));
List实现类
  • ArrayList[重点]:

    • 数组结构实现,查询快、增删慢;

    • JDK1.2版本,运行效率快、线程不安全。

ArrayList类add()方法源码分析:

默认容量:DEFAULT_CAPACITY = 10

注意:如果没有向集合中添加任何元素,容量为0; 添加任意一个元素之后,容量为10;每次扩容大小为原来的1.5倍

存放元素的数组:Object[] elementData

实际元素个数:size

添加方法:add()

public boolean add(E e) {
   ensureCapacityInternal(size + 1);  // Increments modCount!!
   elementData[size++] = e;
   return true;
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
   if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
       return Math.max(DEFAULT_CAPACITY, minCapacity);
  }
   return minCapacity;
}
private void ensureCapacityInternal(int minCapacity) {
   ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
  modCount++;
  if (minCapacity - elementData.length > 0)
      grow(minCapacity);
}
private void grow(int minCapacity) {
       // overflow-conscious code
       int oldCapacity = elementData.length;
       int newCapacity = oldCapacity + (oldCapacity >> 1);
       if (newCapacity - minCapacity < 0)
           newCapacity = minCapacity;
       if (newCapacity - MAX_ARRAY_SIZE > 0)
           newCapacity = hugeCapacity(minCapacity);
       // minCapacity is usually close to size, so this is a win:
       elementData = Arrays.copyOf(elementData, newCapacity);
  }
  • Vector:

    • 数组结构实现,查询快、增删慢;

    • JDK1.0版本,运行效率慢、线程安全。

  • LinkedList:

    • 链表结构实现,增删快,查询慢。

LinkedList类add()方法源码分析:

int size; 集合大小

Node first; 链表的头节点

Node last; 链表的尾节点

Node 节点

void linkLast(E e) {
  final Node<E> l = last;
  final Node<E> newNode = new Node<>(l, e, null);
  last = newNode;
  if (l == null)
      first = newNode;
  else
      l.next = newNode;
  size++;
  modCount++;
}
ArrayList和LinkedList的区别

不同结构的实现方式

ArrayList:必须开辟连续空间,查询快,增删慢。 LinkedList:无需开辟连续空间,查询慢,增删快。

泛型
  • Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。

  • 常见形式有泛型类、泛型接口、泛型方法

  • 语法:

    • <T,…> T称为类型占位符,表示一种引用类型。

  • 好处:

    • (1)提高代码的重用性

    • (2)防止类型转换异常,提高代码的安全性

泛型集合
  • 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。

  • 特点:

    • 编译时即可检查,而非运行时抛出异常。

    • 访问时,不必类型转换(拆箱)

    • 不同泛型之间引用不能相互赋值,泛型不存在多态。

Set子接口

特点:无序,无下标,元素不可重复

方法:全部继承自Collection中的方法。

Set实现类
HashSet[重点] :
  • 基于HashCode实现元素不重复。

  • 当存入元素的哈希码相同时,会调用equals进行确认, 如结果为true,则拒绝后者存入。

  • 存储结构:哈希表(数组+链表+红黑树【JDK1.8之后】)

  • 存储过程:

    • (1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步

    • (2)再执行equals方法,如果equals方法为true,则认为是重复,否则形成链表

equals()方法与hashcode()方法重写

@Override
public int hashCode() {
  int n1 = this.name.hashCode();
  int n2 = this.age;
  return n1+n2;
}
@Override
public boolean equals(Object obj) {
  //判断是否同一个对象
  if (this == obj){
      return true;
  }
  //判断对象是否为空
  if (obj == null){
      return false;
  }
  //判断对象是否属于Person
  if (obj instanceof Person) {
      Person s = (Person) obj;
      //判断属性是否相等
      if (this.name.equals(s.getName()) && this.age == s.getAge()){
          return true;
      }
  }
  //不满足条件返回false
  return false;
}
TreeSet:
  • 基于排列顺序实现元素不重复。

  • 实现了SortedSet接口, 对集合元素自动排序。

  • 元素对象的类型必须实现Comparable接口,指定排序规则。

  • 通过CompareTo方法确定是否为重复元素。

  • 存储结构:红黑树

ClassCastException解决方法:CompareTo方法重写

//先按姓名比,再按年龄比
@Override
public int compareTo(Person o) {
  int n1 = this.name.compareTo(o.getName());
  int n2 = this.age - o.getAge();

  return n1 == 0 ? n2 : n1;
}

Comparator:实现定制比较(比较器)

TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
  @Override
  public int compare(Person o1, Person o2) {
      int n1 = o1.getAge() - o2.getAge();
      int n2 = o1.getName().compareTo(o2.getName());
      return n1 == 0 ? n2 : n1;
  }
});

Map体系集合

interface Map的特点:

  1. 用于存储任意键值对(Key-Value)

  2. 键:无序、无下标、不允许重复(唯一)

  3. 值:无序、无下标、允许重复

Map父接口
  • 特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复。

  • 方法:

    • V put(K key,V value) //将对象存入到集合中,关联键值。key重复则覆盖原值。

    • 0bject get (0bject key) //根据键获取对应的值。

    • Set<K> keySet() //返回此映射中包含的键的 Set 视图。

    • Collection<V> values() //返回包含所有值的Collection集合。

    • Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的 Set 视图。

//3 遍历
//3.1 使用keySet();
System.out.println("--------keySet()----------");
//Set<String> keySet = map.keySet();
for (String key: map.keySet()) {
  System.out.println(key +"------"+ map.get(key));
}
//3.2 使用entrySet();
System.out.println("--------entrySet()----------");
//Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry: map.entrySet()) {
  System.out.println(entry.getKey() +"------"+ entry.getValue());
}

Map集合的实现类
HashMap[重点]:

JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value。

  • 基于哈希表的Map接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。

  • HashMap() 构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。

  • 方法:同Map接口

  • 存储结构:哈希表(数组+链表+红黑树)

  • 使用key的hashcode()和equals()作为重写:

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return stuNo == student.stuNo && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, stuNo);
}
HashMap源码分析
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16//hashMap初始容量大小
static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap的数组最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
static final int TREEIFY_THRESHOLD = 8;//jdk1.8 当链表长度大于8时,调整成红黑树
static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8 当链表长度小于6时,调整成链表
static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当链表长度大于8时,并且集合元素大于等于64时,调整成红黑树
transient Node<K,V>[] table;//哈希表中数组
transient int size;//元素个数

无参构造

public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

put方法

public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}

源码分析总结:

  1. HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16

  2. 当元素个数大于阈值(16*0.75=12)时, 会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数。

  3. jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率

  4. jdk1.8 当链表长度小于6时,调整成链表

  5. jdk1.8 以前,链表时头插入,jdk1.8以后时是尾插入

Hashtable:

JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。

构造方法:Hashtable() 用默认的初始容量 (11)加载因子 (0.75) 构造一个新的空哈希表。

Properties:

Hashtable的子类,要求key和value都是String。 通常用于配置文件的读取。

Properties类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

TreeMap :

实现了SortedMap接口(是Map的子接口),可以对key自动排序。

* ClassCastException
* implements Comparable<Student>   compareTo(Student o)
* @author mamba
@Override
public int compareTo(Student o) {
  int n1 = this.stuNo-o.getStuNo();
  return n1;
}
TreeMap<Student, String> students = new TreeMap<>(new Comparator<Student>() {
  @Override
  public int compare(Student o1, Student o2) {
      int n1 = o1.getStuNo() - o2.getStuNo();
      return n1;
  }
});

Collections工具类

  • 概念:集合工具类,定义了除了存取以外的集合常用方法。

    此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。

  • 方法:

    • public static void reverse(List<?> list) //反转集合中元素的顺序

    • public static void shuffle(List<?> list) //随机重置集合元素的顺序

    • public static void sort(List<T> list) //升序排序(元素类型必须实现Comparable接口)

    • static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)

      //使用二分搜索法搜索指定列表,以获得指定对象。

    • static <T> void copy(List<? super T> dest, List<? extends T> src)

      //将所有元素从一个列表复制到另一个列表。

    • static void reverse(List<?> list) //反转指定列表中元素的顺序。

版权声明:本文为MambaHonor原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/mambahonor/p/16040770.html