集合
1.集合
-
概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
-
和数组区别:
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型。
-
位置: java.util.*
-
Collection体系集合
2.Collection父接口
-
特点:代表一组任意类型的对象,无序、无下标、不能重复。
-
方法:
- boolean add(0bject obj) //添加一个对象。
- boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中。
- void clear() //清空此集合中的所有对象。
- boolean contains(Object o) //检查此集合中是否包含o对象。
- boolean equals(0bject o) //比较此集合是否与指定对象相等。
- boolean isEmpty() //判断此集合是否为空
- boolean remove(0bject o) //在此集合中移除o对象
- int size() //返回此集合中的元素个数。
- 0bject[] toArray() //将此集合转换成数组。
-
//新建Colletion对象 Collection collection = new ArrayList(); student s1 = new student("张三",20); student s2 = new student("李四",21); student s3 = new student("王五",22); //1 添加数据 collection.add(s1); collection.add(s2); collection.add(s3); System.out.println("元素个数:" + collection.size()); System.out.println(collection.toString()); //2删除 //collection.remove(s1); System.out.println("删除之后:" + collection.size()); //3遍历 for (Object o : collection) { student s = (student)o; System.out.println(s.toString()); } //3.2迭代器 Iterator it = collection.iterator(); while (it.hasNext()){ student s = (student)it.next(); System.out.println(s.toString()); } //4判断 System.out.println(collection.contains(s1)); System.out.println(s1.toString());
3.List子接口
- 特点:有序、有下标、元素可以重复。
- 方法:
- void add(int index,0bject o) //在index位置插入对象o。
- boolean addAll(int index,Collection c) //将一个集合中的元素添加到此集合中的index位置。
- 0bject get(int index) //返回集合中指定位置的元素。
- List subList(int fromIndex,int tolndex) //这凹fromIndex个toIndex之间的集合元素。
List实现类
- ArrayList【重点】:
- 数组结构实现,查询快、增删慢;
- .JDK1.2版本,运行效率快、线程不安全。
- 源码分析:
- DEFAULT_CAPACITY = 10,默认容量
- 注意:如果没有向集合中添加任何元素时,容量为0,添加任意元素后容量为10,每次扩容为原来的1.5倍
- elementData存放元素的数组
- size 实际元素个数
- DEFAULT_CAPACITY = 10,默认容量
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
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:
- 添加删除和判断其他的差不多,主要是在遍历这处理for循环,和增强for循环 。还有一个枚举器,其他的方法Fristelement、Lastelement
- 数组结构实现,查询快、增删慢。
- JDK1.0版本,运行效率慢、线程安全。
-
LinkedList:
-
链表结构实现,双向链表,增删快,查询慢。通过更改指向来进行增删元素
-
int size:集合的大小
-
Node frist:链表的头节点
-
Node last:链表的尾节点
public boolean add(E e) { linkLast(e); return true; } 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++; } ``
-
4.泛型
4.1、泛型概念
-
Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
-
常见形式有泛型类、泛型接口、泛型方法。
-
语法:
- <T,… >T称为类型占位符,表示一种引用类型。
-
好处:
-
提高代码的重用性
-
防止类型转换异常,提高代码的安全性
-
示例:
ublic class MyGeneric<T> {
//使用泛型
//1 创建变量
T t;
//2 泛型作为方法的参数
public void show(T t){
System.out.println(t);
}
//3 泛型作为方法的返回值
public T getT(){
return t;
}
}
MyGeneric<String> myGeneric = new MyGeneric<String>();
myGeneric.t = "hello";
myGeneric.show("现在是22:10");
MyGeneric<Integer> myGeneric1 = new MyGeneric<Integer>();
myGeneric1.t=100;
myGeneric1.show(200);
Integer integer = myGeneric1.getT();
4.2、泛型集合
- 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
- 特点:
- 编译时即可检查,而非运行时抛出异常。访问时,不必类型转换(拆箱)。
- 不同泛型之间引用不能相互赋值,泛型不存在多态
5.set集合
5.1 set子接口
- 特点:无序、无下标、元素不可重复。
- 方法:全部继承自Collection中的方法。
5.2.Set实现类
- HashSet【重点】:
- 基于HashCode实现元素不重复。
- 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
- 基于HashCode计算元素存放位置
- 存储过程(很重要)
(1)根据hashcode计算保存的位置。如果此位置为空,则直接保存,如果不为空执行第二步
(2)再执行equals方法,如果equals方法为ture,则认为是重复,否则,形成链表
!!!先重写hashcode保证相同属性对象生成相同哈希值,不然两个属性相同的对象依然分到不同的数组
- TreeSet(二叉树):
- 基于排列顺序实现元素不重复。
- 实现了SortedSet接口,对集合元素自动排序。
- 元素对象的类型必须实现Comparable接口,指定排序规则。
- 通过CompareTo方法确定是否为重复元素。
- 存储结构:红黑树
如果没有比较规则的话会出现ClassCastException类型转换错误
要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
6.Map集合
6.1Map父接口
-
特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复。
-
方法:
- v put(K key,v value) //将对象存入到集合中,关联键值。key重复则覆盖原值。
- 0bject get(object key) //根据键获取对应的值
- Set //返回所有key。
- Collection values() //返回包含所有值的Collection集合。
- set<Map.Entry<K,V>> //键值匹配的Set集合。
-
源码分析:
- static final int DEFAULT_INITIAL_CAPACITY = 1 <<4; //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_TREETFY_CAPACITY = 64; // jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑数
- transient Node<K, V>[] table; //哈希表中的数组
- size; //元素个数
-
总结:
- HashMap刚创建时,table是null,为了节省空间,添加第一个元素时,table容量调整为16
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数。
- jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
- jdk1.8当链表长度小于6时,调整成链表
- jdk1.8以前,链表时头插入,jdk1.8以后时是尾插入
-
HashMap【重点】:
- JDK1.2版本,线程不安全,运行效率快;允许用null 作为key或是value。
-
Hashtable :
- JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。
-
Properties (流):
- Hashtable的子类,要求key和value都是String。
- 通常用于配置文件的读取。
-
TreeMap
- 实现了SortedMap接口(是Map的子接口),可以对key自动排序。
7.Collection工具类
- 概念:集合工具类,定义了除了存取以外的集合常用方法。
- 方法:
- public static void reverse(List<?> list)//反转集合中元素的顺序.
- public static void shuffle(List<?> list)//随机重置集合元素的顺序.
- public static void sort(List list)//升序排序(元素类型必须实现Comparable接口)
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(2);
list.add(10);
list.add(12);
list.add(25);
//sort排序
System.out.println(list.toString());
Collections.sort(list);
System.out.println(list.toString());
//binarySerch二分查找
int k = Collections.binarySearch(list,20);
System.out.println(k);
//copy复制,要求源集合和目标集合的长度相同
List<Integer> dest = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
dest.add(0);
}
Collections.copy(dest,list);
System.out.println(dest.toString());
//reverse反转
Collections.shuffle(list);
System.out.println("反转之后:" + list);
//shuffle 打乱
Collections.shuffle(list);
System.out.println("打乱之后:" + list);
//补充:list转成数组
Integer[] arr = list.toArray(new Integer[0]);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//数组转成集合
System.out.println("-------------数组转成集合--------------");
String[] names = {"张三", "李四", "王五"};
//集合是一个受限集合,不能添加和删除
List<String> list1 = Arrays.asList(names);
System.out.println(list1);
//把基本类型数组转换为集合时,需要修改为包装类型
Integer[] nums = {100,15,415,456,15,77,9};
List<Integer> list2 = Arrays.asList(nums);
System.out.println(list2);
8.集合总结
- 集合的概念:
- 对象的容器,和数组类似,定义了对多个对象进行操作的常用方法。
- List集合:
- 有序、有下标、元素可以重复。(ArrayList、LinkedList、Vector)
- Set集合:
- 无序、无下标、元素不可重复。(HashSet、TreeSet)。
- Map集合:
- 存储一对数据,无序、无下标,键不可重复,值可重复。(HashMap、HashTable、TreeMap)
- Collections:
- 集合工具类,定义了除了存取以外的集合常用方法。