一. List集合
1. ArrayList
- 底层:是一个Object[]
- 长度:0–10–
- 扩容时机:数组不够用的时候(长度10,添加第11个时)
- 扩容后的长度:new = old + old >> 1 1.5倍
2. LinkedList
LinkedList是List集合一种实现类,底层是链表
- 有三个属性, size, Node first, Node last
- Node 表示就是链表,有三个属性 item(保存值),Node next(下一个), Node prev(上一个)
- 每一个添加数组
- 创建一个Node 对象使用item属性保存值
- 获取原来的最后一个节点,把当前节点的上一个节点设置原来的最后一个节点
- 把当节点设置最后节点
public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
//集合中元素个数
int size = 0;
//头节点 (第一个环)
Node<E> first;
//未节点 (最后一个环)
Node<E> last;
/*
* 这就是链子上每个环(节点)的类
* 我们每保存一个值,就会创建一个Node对象
*/
private static class Node<E> {
E item; //保存我们添加的值
Node<E> next; //下一个节点
Node<E> prev; //上一个节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
//添加方法
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
//获取最后一个节点
final Node<E> l = last;
//使用有参构造方法创建一个Node对象,把原来的最后节点设置为当前节点上一个节点
final Node<E> newNode = new Node<>(l, e, null);
//把当前节点设置为最后一个节点
last = newNode;
//如果是第一次添加,也把当前节点设置为第一个节点
if (l == null) {
first = newNode;
} else {
//如果不是第一次添加,把原来的最后一个节点后面节点设置为当前节点
l.next = newNode;
}
//元素个数加1
size++;
modCount++;
}
}
package com.qfedu;
import java.util.LinkedList;
import java.util.List;
public class Demo01 {
public static void main(String[] args) {
List<String> list = new LinkedList<String>();
list.add("jackma");
list.add("pony");
list.add("robin");
list.set(1, "pony teng");
String name = list.get(1);
list.remove(1);
}
}
3. 比较ArrayList和LinkedList的区别
- ArrayList的底层是数组,LinkedList底层是链表
- ArrayList的查询速快,但是插入和删除的效率低下
- LinkedList插入和删除的速度快,查询的速度比较慢
4. Vector
Vector是List集合的一个实现类
- 底层是一个数组,可以看做是一个低配版的ArrayList
- Vector的方法,都使用synchronized进行修饰,表示的是线程安全的意思
- 如果在多线程的编程情况下,必须使用线程安全的集合
- ArrayList和LinkedList都是线程不安全的
二. Set集合
Set集合是Colletion集合的子接口,表示的是无序且不可重复的集合
- HashSet
- LinkedHashSet
- TreeSet
1. HashSet
HashSet是Set集合的一个现实类
- 底层是HashMap
- 当保存一个值时,就往HashMap中一个键值对,保存的值作为键值对的key,值就是new出来的Object对象
package com.qfedu;
import java.util.HashSet;
import java.util.Set;
public class Demo03 {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("jackma");
set.add("pony");
set.add("pony");
set.add("robin");
Set<A> set2 = new HashSet<A>();
set2.add(new A(1, 1));
set2.add(new A(2, 1)); //如果出现重复数据,则不会添加成功(不会覆盖前面的值)
System.out.println(set2);
}
}
class A {
int b;
int c;
public A() {
}
public A(int b, int c) {
super();
this.b = b;
this.c = c;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + c;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
A other = (A) obj;
if (c != other.c)
return false;
return true;
}
@Override
public String toString() {
return "A [b=" + b + ", c=" + c + "]";
}
}
2. LinkedHashSet
LinkedHashSet是Set集合的一个现实类,会保存元素添加的顺序。
package com.qfedu;
import java.util.LinkedHashSet;
import java.util.Set;
public class Demo04 {
public static void main(String[] args) {
/*
* 保存 添加元素顺序的set集合
*/
Set<String> set = new LinkedHashSet<String>();
set.add("jackma");
set.add("pony");
set.add("pony");
set.add("robin");
for(String str : set) {
System.out.println(str); //按照保存顺序 jackma pony robin
}
}
}
3. TreeSet
TreeSet是Set集合的一个现实类,可以根据自动规则对数据进行排序
- 泛型必须实现Comparable接口
- 判断两个元素是否重复的依据为重写后compareTo方法的结果是否为零
- 整数 大于
- 零 等于 后面的元素则会添加失败
- 负数 小于
- TreeSet底层为TreeMap
package com.qfedu;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
public class Demo05 {
public static void main(String[] args) {
/*
* 1. 把学生信息(对象) 保存在Set集合 2. 根据成绩排序 2.1如果成绩相同,就根据姓名排序 2.2如果成绩和姓名都相同,就根据学号降序
*
*/
Student stu1 = new Student("jackma", 96, "1100");
Student stu2 = new Student("pony", 89, "1200");
Student stu3 = new Student("jaaes", 96, "1300");
Student stu4 = new Student("kobe", 91, "1400");
Student[] arr = { stu1, stu2, stu3, stu4 };
Arrays.sort(arr);
for (Student stu : arr) {
System.out.println(stu);
}
System.out.println("===========================================");
/*
* TreeSet会自动为添加的元素排序
*
* 1. TreeSet的泛型类,必须实现Comparable接口 2. 判断元素是否重复的标准就是compareTo接口是否为0 3.
* 我们使用一定要谨慎使用,一定要比较到那个唯一的属性
*/
Set<Student> set = new TreeSet<Student>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
for (Student s : set) {
System.out.println(s);
}
}
}
class Student implements Comparable<Student> {
String name;
int score;
String code;
public Student(String name, int score, String code) {
super();
this.name = name;
this.score = score;
this.code = code;
}
/*
* 整数 大于 零 等于 负数 小于
*/
@Override
public int compareTo(Student o) {
int r = score - o.score;
if(r != 0) { return r; }
r = this.name.compareTo(o.name);
if (r != 0) { return r; }
return this.code.compareTo(o.code);
}
@Override
public String toString() {
return "Student [name=" + name + ", score=" + score + ", code=" + code + "]";
}
/*
* 定义手机类
* 价格 double
* 重量 double
* 编号 String
*
* 价格降序排列
* 价格相同,重量升序排
* 价格,重量都相同,则根据编号升序
*/
}
三. Map
在java中使用集合,就这三种:List Set Map
Map是一种集合,是一种键值对的集合,说白了,就是在保存一个值的时候,给这个值起个名字
public interface Map<K,V> {
//返回键值对的个数
int size();
//判断是否为空
boolean isEmpty();
//是否包含key或者value
boolean containsKey(Object key);
boolean containsValue(Object value);
//
V get(Object key);
//添加
V put(K key, V value);
//根据key删除
V remove(Object key);
void putAll(Map<? extends K, ? extends V> m);
//清空
void clear();
//获取所有键值对的key
Set<K> keySet();
Collection<V> values();
/*
* 每一个键值对,都可以看做一个Entry<K, V>对象
* 我们可以通过获取每一个Entry<K, V>对象获取其中key和value值
*/
Set<Map.Entry<K, V>> entrySet();
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
}
}
1. 常用方法
package com.qfedu;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Demo06 {
public static void main(String[] args) {
/*
* Map:表示的是一种键值对的集合:相当于在保存一个值时,给这个值起一个名
* 把保存的值成为value,把给这个值起的名字叫做键:key
* 在定义Map时,需要定义两个泛型,第一个泛型表示key的类型,第二个泛型表示保存值(value)的类型
*/
Map<Integer, String> map = new HashMap<Integer, String>();
/*
* isEmpty() 判断是否为空
*/
System.out.println(map.isEmpty());
/*
* V put(K key, V value); 添加值,,修改值
* 1. key不能重复,如果出现出现的key,不会添加成功,但后面的value会覆盖掉前面的value。
* 1.1 重复的条件:equals结果为ture,hashCode要相等
* 2. key,value都可以为null
*/
map.put(1, "鲁迅");
map.put(2, "李敖");
map.put(3, "莫言");
map.put(3, "余华");
map.put(null, null);
/*
* int size(); 获取保存值的个数
*/
int size = map.size();
System.out.println(size);
/*
* V get(Object key); 根据key获取保存的值
*/
String v = map.get(3);
System.out.println(v);
/*
* boolean containsKey(Object key);
* boolean containsValue(Object value);
*/
System.out.println(map.containsKey(2));
System.out.println(map.containsValue("莫言"));
/*
* V remove(Object key);
*/
map.remove(null);
System.out.println(map.size());
/*
* 遍历map集合
* 1. 先获取所有的key,根据key获取所有的value
* 2. 获取Entry的集合,遍历得到每一个Entry对象
*/
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
System.out.println("key:"+key+" value:"+map.get(key));
}
/*
* 我们保存的每个键值对,都可以看做是一个Entry的对象
*/
Set<Entry<Integer, String>> entrySet = map.entrySet();
for(Map.Entry<Integer, String> entry : entrySet) {
System.out.println(entry.getKey() +":"+entry.getValue());
}
}
}
2. 常用实现类
- HashMap
- Hashtable
- TreeMap
2.1 HashMap
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
//添加键值对的个数
transient int size;
//默认初始化容量(长度)
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认加载因子(数组扩容的一个临界值)
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//树化的阈值 (二叉树,红黑树)
static final int TREEIFY_THRESHOLD = 8;
//反树化的阈值 (二叉树,红黑树)
static final int UNTREEIFY_THRESHOLD = 6;
//最小树化容量
static final int MIN_TREEIFY_CAPACITY = 64;
int threshold;
final float loadFactor;
//就是添加键值对的位置
transient Node<K,V>[] table;
//我们往map集合中添加一个键值对时,实际上添加就是Node对象
static class Node<K,V> implements Map.Entry<K,V> {
final int hash; //保存的Key的hashCode值
final K key; //保存key值
V value; //保存value值
Node<K,V> next; //保存下面的那个Node对象 单向链表
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
/*
* 有参构造方法
* initialCapacity : 初始容量
* loadFactor :加载因子
*/
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
}
2.2 Hashtable
Hashtable是Map集合的一个实现类,它是线程安全的
2.3 TreeMap
TreeMap是Map集合的一个实现类,它会显示对Key值的自动排序
package com.qfedu;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Demo07 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>(19,77);
Map<String,String> map2 = new Hashtable<String,String>(19,77);
Map<String,Integer> map3 = new TreeMap<String,Integer>();
map3.put("jackma",88);
map3.put("abert",99);
map3.put("bean",33);
map3.put("macke",21);
map3.put("wade",56);
Set<String> keySet = map3.keySet();
for(String key : keySet) {
System.out.println(key +":"+ map.get(key));
}
}
}