JAVA-集合框架篇
集合
- 概念:对象的容器,定义了对多个对象进行操作的常用方法,可实现数组的功能
与数组的区别:
- 数组长度固定,集合长度不固定
- 数组可以存储基本数据类型和引用类型,集合只能存储引用类型,当储存基本数据类型的时候会自动装箱
- 位置:java.util.*;
Collection
import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;public class Test11 { public static void main(String[] args) { //todo 创建集合 Collection collection = new ArrayList(); //todo 添加元素 collection.add("chen"); collection.add("xing"); collection.add("en"); // 获取集合大小 System.out.println(collection.size()); //删除元素 collection.remove("chen"); System.out.println(collection.size()); //遍历集合 // todo 1.使用增强for循环遍历 for (Object o : collection) { System.out.println(o); } // todo 2.使用迭代器 Iterator iterator = collection.iterator(); while (iterator.hasNext()){ Object o=iterator.next(); System.out.println(o); //迭代器内不允许使用collection.remove(); //可以使用iterator.remove(); } //todo 判断集合中是否有某元素 System.out.println(collection.contains("xin")); System.out.println(collection.contains("xing")); // todo 判断集合是否为null System.out.println(collection.isEmpty()); // todo 清空集合 collection.clear(); System.out.println(collection.isEmpty()); }}
List
特点:有序(添加顺序与遍历顺序)、有下标、元素可重复
import java.util.ArrayList;import java.util.List;import java.util.ListIterator;public class Test12 { public static void main(String[] args) { List objects = new ArrayList<>(); objects.add("chen"); objects.add("cx"); // todo 角标遍历 for (int i=0;i<objects.size();i++){ System.out.println(objects.get(i)); } // todo 使用列表迭代器 ListIterator listIterator = objects.listIterator(); while(listIterator.hasNext()){ System.out.println(listIterator.nextIndex()+":"+listIterator.next()); } //指针,所以必须先使用hasNext while(listIterator.hasPrevious()){ System.out.println(listIterator.previousIndex()+":"+listIterator.previous()); } //判断 System.out.println(objects.contains("chen")); System.out.println(objects.isEmpty()); //获取位置 System.out.println(objects.indexOf("cx")); }}
import java.util.ArrayList;import java.util.List;public class Test13 { public static void main(String[] args) { List objects = new ArrayList<>(); //进行了自动装箱处理 objects.add(20); objects.add(30); System.out.println(objects.size()); //截取,含头不含尾 System.out.println(objects.subList(1,2)); //删除操作 objects.remove(0); //objects.remove(20);此处是索引 System.out.println(objects); objects.remove(new Integer(30)); System.out.println(objects);//[] }}
- ArrayList
1.数据结构实现,查询快,增删慢;
2.JDK1.2版本,运行效率快、线程不安全- Vector
1.数组结构实现,查询快、增删慢;
2.JDK1.0版本,运行效率慢、线程安全- LinkedList
1.链表结构实现,增删快,查询慢
ArrayList
创建ArrayList初始容量为0 ,当添加第一个元素时,容量变为10,扩容时,每次为前一次的1.5倍
public class Student implements Serializable { private String name; private String age; public Student() { } public Student(String name, String age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } //重写比较方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return name.equals(student.name) && age.equals(student.age); } //重写toString方法 @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; }}
public class Test14 { public static void main(String[] args) { ArrayList<Object> objects = new ArrayList<>(); objects.add(new Student("12","c")); objects.add(new Student("12","x")); System.out.println(objects); //删除元素,此时需要重写equals方法,才能删除列表中的Student("12","c") objects.remove(new Student("12","c")); System.out.println(objects); }}
LinkedList
public class Test18 { public static void main(String[] args) { LinkedList<Object> objects = new LinkedList<>(); objects.add("c"); objects.add("x"); //迭代器遍历 Iterator<Object> iterator = objects.iterator(); while (iterator.hasNext()){ Object next = iterator.next(); System.out.println(next); } }}
Vector
public class Test17 { public static void main(String[] args) { Vector<Object> objects = new Vector<>(); objects.add("c"); objects.add("x"); System.out.println(objects.size()); //遍历:使用枚举器 Enumeration<Object> elements = objects.elements(); while (elements.hasMoreElements()){ Object o = elements.nextElement(); System.out.println(o); } }}
Set
特点:无序(添加顺序与遍历顺序)、无下标、元素不可重复
HashSet
- 基于HashCode实现元素不重复。
- 当存入元素的哈希码相同时,会调用equals进行确认,若结果为true,则拒绝后者存入
- 底层实际是用的HashMap
import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class Test21 { public static void main(String[] args) { Set<String> objects = new HashSet<String>(); objects.add("c"); objects.add("x"); System.out.println(objects.size()); //迭代器遍历 Iterator<String> iterator = objects.iterator(); while (iterator.hasNext()){ String next = iterator.next(); System.out.println(next); } boolean x = objects.contains("x"); System.out.println(x); }}
package com.utils;import java.io.Serializable;import java.util.Objects;public class Student implements Serializable { private String name; private String age; public Student() { } public Student(String name, String age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } //重写比较方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return name.equals(student.name) && age.equals(student.age); } //重写toString方法 @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } //重写hashcode @Override public int hashCode() { //31 是一个质数,减少散列冲突,提高执行效率 31*i=(i<<5)-i final int prime=31; int result=1; result=prime*result+((this.name==null)?0:(this.name.hashCode())); result=prime*result+((this.age==null)?0:(this.age.hashCode())); return result; }}
package com.utils;import java.util.HashSet;/** * 存储结构:哈希表(数组+链表+红黑树) * 存储过程: * 根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步, * 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表 */public class Test22 { public static void main(String[] args) { HashSet<Student> students = new HashSet<>(); Student student1 = new Student("c","1"); Student student2 = new Student("x","2"); students.add(student1); students.add(student2); //此时加不进来 students.add(new Student("x","2")); System.out.println(students.toString()); }}
TreeSet
- 基于排列顺序实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable接口,指定排序规则
- 通过CompareTo方法确定是否为重复元素
package com.utils;import java.io.Serializable;import java.util.Objects;public class Student implements Serializable,Comparable<Student>{ private String name; private String age; public Student() { } public Student(String name, String age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } //重写比较方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return name.equals(student.name) && age.equals(student.age); } //重写toString方法 @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } //重写hashcode @Override public int hashCode() { //31 是一个质数,减少散列冲突,提高执行效率 31*i=(i<<5)-i final int prime=31; int result=1; result=prime*result+((this.name==null)?0:(this.name.hashCode())); result=prime*result+((this.age==null)?0:(this.age.hashCode())); return result; } //按姓名比,再按年龄比 @Override public int compareTo(Student o) { int n1=this.getName().compareTo(o.getName()); int n2=this.getAge().compareTo(o.getAge()); return n1==0?n2:n1; }}
/** * 存储结构:红黑树 * 要求:元素必须要实现Comparable接口 */public class Test23 { public static void main(String[] args) { TreeSet<Student> students = new TreeSet<Student>(); Student student4 = new Student("cx","3"); Student student1 = new Student("cx","1"); Student student2 = new Student("zx","3"); Student student3 = new Student("zx","2"); students.add(student1); students.add(student2); students.add(student3); students.add(student4); System.out.println(students.toString()); }}
Comparator接口
import java.util.Comparator;import java.util.TreeSet;/** * Comparator实现定制比较 */public class Test24 { public static void main(String[] args) { //创建集合并指定比较规则 TreeSet<Student> students1 = new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { int n1=o1.getName().compareTo(o2.getName()); int n2=o2.getAge().compareTo(o2.getAge()); return n1==0?n2:n1; } }); //Student student4 = new Student("cxc","3"); //Student student1 = new Student("cxc","1"); Student student2 = new Student("zxz","3"); Student student3 = new Student("zxz","21"); //students.add(student1); students1.add(student2); students1.add(student3); //students.add(student4); System.out.println(students1.toString()); }}
Iterator
Map
用于存储任意键值对(Key-Value),无序、无下标、键不允许重复(唯一),值可以
- 常用方法
public class Test25 { public static void main(String[] args) { Map<String, String> stringStringHashMap = new HashMap<String, String>(); stringStringHashMap.put("cx","12"); stringStringHashMap.put("zx","13"); stringStringHashMap.put("vx","14"); //遍历keySet Set<String> strings = stringStringHashMap.keySet(); for (String key : strings) { System.out.println(key+":"+stringStringHashMap.get(key)); } //entrySet Set<Map.Entry<String, String>> entries = stringStringHashMap.entrySet(); for (Map.Entry<String, String> entry : entries) { System.out.println(entry.getKey()+":"+entry.getValue()); } } }
HashMap
- 存储结构:哈希表
- 重复依据:键的hashCode()方法和equals()方法
- HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍,目的是减少调整元素的个数
- jdk 1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整成红黑树,目的提高执行效率
- jdk 1.8 当量表长度小于6时,调整成链表
- jdkv 1.8以前 链表是头插入,jdk1.8以后是尾插入
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//初始容量大小 static final int MAXIMUM_CAPACITY = 1 << 30;//数组最大容量 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;//哈希表中的数组
Hashtable
Properties
TreeMap
实现了SortedMap接口(是Map的子接口),可以对key自动排序
存储接口:红黑树
如果key是实体类,那么该类需要实现Comparable接口,重写CompareTo方法
Collections 工具类
public class Test26 { public static void main(String[] args) { ArrayList<Integer> integers = new ArrayList<>(); integers.add(12); integers.add(1); integers.add(13); //排序 Collections.sort(integers); System.out.println(integers); //binarySearch二分查找,找到了返回其所在的索引,否则返回一个小于0的数 int i = Collections.binarySearch(integers, 12); int j = Collections.binarySearch(integers, 2); System.out.println(i+":"+j); //Copy复制 ArrayList<Integer> dest = new ArrayList<>(); //必须集合大小一致 for (Integer integer : integers) { dest.add(0); } Collections.copy(dest,integers); System.out.println(dest.toString()); //翻转排序 Collections.reverse(dest); System.out.println(dest); //打乱顺序 Collections.shuffle(dest); System.out.println(dest); //list转数组 Integer[] ts = dest.toArray(new Integer[dest.size()]); System.out.println(Arrays.toString(ts)); //数组转list,但是是一个受限集合,不能使用list方法 List<Integer> integers1 = Arrays.asList(ts); //integers1.add(2); System.out.println(integers1); }}
泛型
- Java泛型是JDK1.5引入的一个新特性,其本质是参数化类型,把类型作为参数传递
- 常见形式泛型类、泛型接口、泛型方法。
- 语法 : T称为类型占位符,表示一种引用类型。
- 好处:
- 提高代码的重用性
- 防止类型转换异常,提高代码的安全性
泛型类
集合工具类,定义了除了存取以外的集合常用方法
/** * 泛型类 * @param */public class Test19<T> { //创建变量 T t; //泛型作为方法参数 public void show(T t){ System.out.println(t); } //泛型作为方法返回值 public T getT(){ return t; } public static void main(String[] args) { //泛型只能使用引用类型,不同泛型对象不能相互复制 Test19<String> stringTest19 = new Test19<>(); stringTest19.t="cxc"; stringTest19.show("cx"); System.out.println(stringTest19.getT()); }}
泛型接口
/** * 泛型接口 * 不能泛型静态常量 * @param */public interface Generics<T> { String name="cx"; //T t;错误 T fun(T t);}
package com.utils;public class GenericsImpl<S> implements Generics<String>{ @Override public String fun(String s) { System.out.println(s); return s; }}class GenericsImpl2<T> implements Generics<T>{ @Override public T fun(T t) { System.out.println(t); return t; }}
package com.utils;public class Test20 { public static void main(String[] args) { GenericsImpl<String> generics = new GenericsImpl<String>(); generics.fun("cx"); GenericsImpl2<Integer> integerGenericsImpl2 = new GenericsImpl2<>(); integerGenericsImpl2.fun(1); }}
泛型方法
/** * 泛型方法 * 语法: 返回值类型 */public class MyGenerics { //泛型方法 public <T> T show(T t){ System.out.println(t); return t; } public static void main(String[] args) { MyGenerics myGenerics = new MyGenerics(); myGenerics.show("cx"); myGenerics.show(12); }}
泛型集合
- 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
- 特点:
- 编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换
- 不同泛型之间引用不能相互赋值,泛型不存在多态