什么是集合:
对象的容器,定义了对多个对象进行操作,类似数组的功能。
集合和数组的区别:
数组长度固定,集合长度不固定
数组可以存储基本类型和引用类型,集合只能存储引用类型
位置: java.util.*
Collection 体系集合
Collection父接口
List 接口
public static void main(String[] args) {
//创建集合对象
List list = new ArrayList<>();
//1添加元素
list.add("苹果");
list.add("小米");
list.add("华为");
list.add("OPPO");
list.add("Vivo");
System.out.println("元素个数:" +list.size());
System.out.println(list.toString());
//2.删除元素
System.out.println("-----使用remove(o)方法删除苹果");
System.out.println("-----使用remove(index)方法删除下标为0的元素------");
list.remove("苹果");//删除方式1
list.remove(0);//删除方式2
System.out.println(list.toString());
//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 o : list) {
System.out.println(o);
}
//3.3迭代器
System.out.println("-----使用迭代器迭代------");
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//3,4使用列表迭代器和iterator的区别
ListIterator lit = list.listIterator();
System.out.println("------使用列表迭代器从前往后遍历-------");
while (lit.hasNext()){
System.out.println(lit.nextIndex() + ":" +lit.next());
}
System.out.println("------使用列表迭代器从后往前遍历-------");
while (lit.hasPrevious()){
System.out.println(lit.previousIndex() + ":" + lit.previous());
}
//4.判断
System.out.println(list.contains("苹果"));
System.out.println(list.isEmpty());
System.out.println(list.indexOf("OPPO"));
}
ArrayList:
- DEFAULT_CAPACITY = 10; 默认容量
注意:如果没有向集合中添加任何元素容为0,添加任意一个元素之后容量为10
每次扩容大写是原来的1.5倍 - ELEMENTDATA 存放元素的数组
- Size 实际的元素个数
- add() 添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
subList()
//3.补充方法sublist,返回子集合,含头不含尾
List subList = list.subList(1, 3);
System.out.println(subList.toString());
ArrayList
数组结构实现,查询快,增删慢
运行效率快、线程不安全
public static void main(String[] args) {
//创建集合
ArrayList<Object> arrayList = new ArrayList<>();
//1,添加元素
Student s1 = new Student("刘德华", 22);
Student s2 = new Student("郭富城", 24);
Student s3 = new Student("梁朝伟", 23);
Student s4 = new Student("黎明", 23);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
arrayList.add(s4);
System.out.println("元素个数:" + arrayList.size());
System.out.println(arrayList.toString());
//2.删除操作 重写equals方法
arrayList.remove(new Student("刘德华",20));//equals(this == obj)
arrayList.remove(s1);
System.out.println("删除之后:" + arrayList.size());
//3.1遍历元素
System.out.println("=====使用for循环进行遍历=====");
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
Iterator<Object> it = arrayList.iterator();
while(it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.toString());
}
//3.2列表迭代器
System.out.println("-------使用列表迭代器顺序遍历元素------");
ListIterator<Object> lit= arrayList.listIterator();
while(lit.hasNext()){
System.out.println(lit.nextIndex() + " :" + lit.next()) ;
}
System.out.println("-------使用列表迭代器逆序遍历元素------");
while(lit.hasPrevious()){
System.out.println(lit.previousIndex() + " :" + lit.previous());
}
//4.判断
System.out.println(arrayList.contains(new Student("刘德华", 22)));
System.out.println(arrayList.isEmpty());
//5.查找
System.out.println(arrayList.indexOf(new Student("黎明", 23)));
}
Vector(向量):
数组结构实现、查询快、增删慢
运行效率慢,线程安全
LinkedList:
链表结构实现,增删快,查询慢
public static void main(String[] args) {
//1.创建元素
LinkedList<Object> linkedList = new LinkedList<>();
Student s1 = new Student("张三",19);
Student s2 = new Student("李四",20);
Student s3 = new Student("王五",23);
Student s4 = new Student("刘六",24);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s4);
System.out.println(linkedList.toString());
//删除元素
System.out.println(linkedList.size());
linkedList.remove(new Student("李四",20));//需要重写equals
linkedList.remove("删除之后:" + linkedList.size());
// linkedList.clear();
//遍历元素
//3.1for 循环
System.out.println("=====使用for循环进行遍历=====");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
//3.2迭代器遍历
System.out.println("=====使用迭代器进行遍历=====");
Iterator<Object> it = linkedList.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//3.3增强for循环
System.out.println("使用增强for循环进行遍历");
for (Object o : linkedList) {
Student s = (Student)o;
System.out.println(s.toString());
}
//3.4列表迭代器
ListIterator<Object> lit = linkedList.listIterator();
while(lit.hasNext()){
System.out.println(lit.nextIndex()+ " :" + lit.next());
}
System.out.println("===============");
while(lit.hasPrevious()){
System.out.println(lit.previousIndex() + " : " + lit.previous());
}
//4.判断
System.out.println(linkedList.contains(new Student("李四",20)));
System.out.println(linkedList.isEmpty());
//5.查找
System.out.println(linkedList.indexOf(new Student("王五",23)));
}
不同结构实现方式
ArraylistArrayList:必须开辟连续空间,查询快,增删慢。LinkedList:无需开辟连续空间,查询慢,增删快。
泛型
参数化类型
常见类型 泛型类、泛型接口、泛型方法
public class MyGeneric<T> {
//使用泛型
//1.使用泛型 注意不能实例化
T t;
//2 作为方法的参数
public void show(T t){
System.out.println(t);
}
//3.泛型作为方法的返回值
public T getT(){
return t;
}
}
语法
<T,E,K,V>
好处:(1)提高代码的重用性
(2)防止类型转换异常,提高代码的安全牲
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
特点:编译时即可检查,而非运行时抛出异常。访问时,不必类型转换(拆箱)。
不同泛型之间引用不能相互赋值,泛型不存在多态。
set 接口
特点:(1) 无序,没有下标 (2)不能重复
public static void main(String[] args) {
//创建集合
Set<String> set = new HashSet<>();
//1.添加数据
set.add("curry");
set.add("james");
set.add("green");
set.add("poor");
set.add("poor");
System.out.println("数据个数" + set.size());
System.out.println(set.toString());
//2.删除数据
set.remove("poor");
// set.clear();
//3.遍历
//3.1增强for
System.out.println("=======使用增强for循环======");
for (String s : set) {
System.out.println(s);
}
//3.2迭代器
System.out.println("=======使用迭代器======");
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//4.判断
System.out.println(set.isEmpty());
System.out.println(set.contains("curry"));
}
HashSet
基于HashCode实现元素不重复。
当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
public static void main(String[] args) {
//创建集合
HashSet<Person> persons = new HashSet<>();
Person p1 = new Person("curry",34);
Person p2 = new Person("james",37);
Person p3 = new Person("green",33);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println("元素个数:"+ persons.size());
System.out.println(persons.toString());
//删除操作
persons.remove(p1);
persons.remove(new Person("curry",34));
System.out.println("删除元素个数:"+ persons.size());
//遍历
//3.1适应增强for
for (Person person : persons) {
System.out.println(person);
}
System.out.println("============");
//3.2迭代器
Iterator<Person> it = persons.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//4.判断
System.out.println(persons.contains(p1));
System.out.println(persons.contains(new Person("curry",34)));
TreeSet
- 基于排序顺序实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable接口,指定排序规则
- 通过CompareTo方法确定是否为重复元素
- 存储结构:红黑树
public static void main(String[] args) {
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;
}
});
//1.添加元素
Person p1 = new Person("curry",34);
Person p2 = new Person("james",37);
Person p3 = new Person("green",33);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println("元素个数:" + persons.size());// 如果不重写comparable接口 ClassCastException cannot be cast to java.lang.Comparable
System.out.println(persons.toString());
//删除
persons.remove(p2);
System.out.println("元素个数:" + persons.size());
//遍历元素
for (Person person : persons) {
System.out.println(person.toString());
}
Iterator<Person> it = persons.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//判断
System.out.println(persons.contains(p1));
System.out.println(persons.contains(new Person("curry",34)));
}
存储过程
(1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步。(2)再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
Map接口
Map接口的特点:
- 用于存储任意键值对
- 无序、无下标、不允许重复(唯一)
- 值:无序、无下标、允许重复
Map集合的使用
//创建Map集合
Map<String,String> map = new HashMap<String,String>();
//1.添加数据
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美国");
System.out.println("元素个数" + map.size());
System.out.println(map.toString());
//2.删除元素
// map.remove("usa");
System.out.println(map.size());
//3.遍历
//3.1使用keySet()1.先拿到所有key的set集合,再通过get获取value值
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println(key + map.get(key));
}
System.out.println("==========");
for (String key : map.keySet()) {
System.out.println(key + map.get(key));
}
//3.2使用entrySet()方法 1.得到键值对映射集合 2.再通过getKey()获取键 getValue()获取值 效率较高
System.out.println("========使用entrySet()方法=========");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey()+ entry.getValue());
}
System.out.println("===========");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + entry.getValue());
}
//4.判断
map.containsKey("cn");
map.containsValue("韩国");
HashMap的使用
public static void main(String[] args) {
//创建集合 刚创建好hashmap 之后没有添加元素 table = null size = 0 节省空间
HashMap<Student ,String> students = new HashMap<Student ,String>();
//添加元素
Student s1 = new Student("curry",100);
Student s2 = new Student("James",101);
Student s3 = new Student("kobe",102);
Student s4 = new Student("zff",103);
students.put(s1,"金州");
students.put(s2,"Los");
students.put(s3,"Los");
students.put(s4,"厦门");
students.put(new Student("curry",100),"金州");//若想要去重,则重写hashcode()和equals()
System.out.println("元素个数:" + students.size());
System.out.println(students.toString());
//删除元素
// students.remove(s4);
// students.remove(s2,"Los");
//3.1 使用keySet()方法遍历元素
System.out.println("========= 使用keySet()方法遍历元素========");
for (Student key : students.keySet()) {
System.out.println(key + students.get(key));
}
//3.2使用entrySet()方法遍历元素
System.out.println("======== 使用entrySet()方法遍历元素========");
for (Map.Entry<Student, String> entry : students.entrySet()) {
System.out.println(entry.getKey() + entry.getValue());
}
//4.判断
System.out.println(students.containsKey(s1));
System.out.println(students.containsValue("北京"));
}
TreeMap的使用
public static void main(String[] args) {
//创建集合
//因为是存储结构是红黑树需要比较 cannot be cast to java.lang.Comparable 需要 1.重写Comparable接口或者2.改造器匿名内部类
// TreeMap<Student,String> treeMap = new TreeMap<Student ,String>(new Comparator<Student>() {
// @Override
// public int compare(Student o1, Student o2) {
// int n1 = o1.getName().compareTo(o2.getName());
// int n2 = o1.getStuNo() - o2.getStuNo();
// return n2 == 0 ? n1:n2;
// }
// });
TreeMap<Student,String> treeMap = new TreeMap<Student,String>();
Student s1 = new Student("curry",200);
Student s2 = new Student("James",6);
Student s3 = new Student("kobe",24);
Student s4 = new Student("zff",47);
treeMap.put(s1,"金州");
treeMap.put(s2,"Los");
treeMap.put(s3,"Los");
treeMap.put(s4,"厦门");
System.out.println("元素个数:" + treeMap.size());
System.out.println(treeMap.toString());
//2.删除元素
treeMap.remove(s1);
//3.遍历元素
System.out.println("=========使用keySet遍历元素=======");
for (Student key : treeMap.keySet()) {
System.out.println( key + treeMap.get(key));
}
System.out.println("=========使用entrySet遍历元素=======");
for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
System.out.println(entry.getKey() + entry.getValue());
}
//4.判断
System.out.println(treeMap.containsKey(s1));
System.out.println(treeMap.containsKey(s4));
}
class =>HashMap=>interface Map
class=> TreeMap=> interface SortMap=>interface Map
hashmap源码分析
1. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//hashMap的初始容量大小
2. static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap的数组最大容量
3. static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
4. static final int TREEIFY_THRESHOLD = 8;//jdk 当链表长度大于8时,调整为红黑树
5. static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8,当链表长度小于6时,形成链表
6. static final int MIN_TREEIFY_CAPACITY = 64;//jik1.8,当链表长度大于8时,并且集合元素个数大于等于64时,调整为红黑树
7. size 元素个数
总结:
- HashMap刚创建时,table是null,当添加第一个元素之后,为了节省空间,Table容量调整为16
- 当元素个数大于阈值(16*0.75 =12时,会出现扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
- jdk1.8,当链表长度大于8时,并且集合元素个数大于等于64时,调整为红黑树,目的提高执行效率
- Jdk1.8之后 当链表长度小于6时,调整为链表
- Jdk1.8以前,链表是头插入,jdk 1.8之后,链表是尾插入
Hashmap 和 HashSet 的关系
HashSet使用 Hashmap的key
TreeSet 使用 TreeMap 的entrySet
Collections方法
- Sort()
- binarySearch()
- Copy()
- Reverse()
- Shuffle()
- 集合转成数组 toarray()
- 数组转成集合 Arrays.aslist()
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(24);
list.add(77);
list.add(10);
list.add(23);
list.add(30);
//sort排序
System.out.println("排序之前:" + list.toString());
Collections.sort(list);
System.out.println("排序之前:" + list.toString());
//binarySearch 大于0 表示找到了 小于0表示没有找到
int n1 = Collections.binarySearch(list, 24);
int n2 = Collections.binarySearch(list, 13);
System.out.println(n1);
System.out.println(n2);
// List<Integer> dest = new ArrayList<Integer>(list.size());
// for (int i = 0; i < list.size(); i++) {
// dest.add(0);
// }
List<Integer> dest = Arrays.asList(new Integer[list.size()]);
Collections.copy(dest,list);
System.out.println(dest.toString());
//reverse反转
Collections.reverse(list);
System.out.println("反转之后:" + list.toString());
//shuffle 打乱
Collections.shuffle(list);
System.out.println("打乱之后:" + list.toString());
//list转成数组
Integer[] arr = list.toArray(new Integer[0]);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
//数组转成集合
String[] names = {"张三", "李四","王五" };
List<String> list2 = Arrays.asList(names);
System.out.println(list2);
//注意:数组转成集合后不能添加和删除