集合框架
目录
1、集合概念
-
对象的容器,实现了对对象常用的操作,类似数组的功能。
-
集合和数组的区别
-
数组长度固定,集合长度不固定。
-
数组可以存储基本类型和引用类型,而集合只存储引用类型。
-
位置;java.util.*;
-
2、Collection体系集合
2.1.Collection体系
2.2、Collection父接口的使用
-
特点:代表一组任意类型的对象,无序、无下标、不能重复。
-
方法:
-
add(Object obj)//添加一个对象
-
addAll(Collection c)//将一个集合中的所有对象都添加到此集合中
-
clear()//清空此集合中的所有对象
-
contains(Object o)//检查此集合中的是否包含o对象
-
equals(Object o)//比较此集合是否和指定对象相等
-
isEmpty()//判断此集合是否为空
-
remove(Object o)//在此集合中移除o对象
-
size()//返回此集合中的元素个数
-
Object[] toArray()//将此集合转换为数组
-
迭代器iterator:专门用来遍历集合的一种方式
-
hasNext();//是否有下一个元素,有就返回true
-
next();//获取下一个元素
-
remove();//删除元素
-
-
代码分析
-
//collection的使用 import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * 1.添加元素 * 2.删除元素 * 3.遍历元素 * 4.查找 */ public class Demo01 { public static void main(String[] args) { Collection collection = new ArrayList(); //1.添加 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 (Object o : collection) { System.out.println(o); } //3.2使用迭代器 iterator用来遍历集合元素的一种方式 Iterator it = collection.iterator(); //hasNext();用来判断是否还有下一个元素 //next();调用下一个元素 //remove():移除下一个元素 while(it.hasNext()){ System.out.println("集合中的元素:"+it.next()); // collection.remove("烧烤");当在迭代器中加上这样一句话的时候,会报并发修改异常(ConcurrentModificationException) // 原因是迭代器中已经创建了对象it,不能在使用collection修改; //it.remove(); } System.out.println("元素个数:"+collection.size()); //4.判断 System.out.println(collection.contains("烧烤")); System.out.println(collection.isEmpty()); } } //Collection的使用:保存学生信息 public class Demo02 { public static void main(String[] args) { Collection collection = new ArrayList(); Student s1 = new Student("懒羊羊", 10); Student s2 = new Student("沸羊羊", 12); Student s3 = new Student("灰太狼", 20); //1.添加信息 collection.add(s1); collection.add(s2); collection.add(s3); // System.out.println("学生个数:"+collection.size()); // System.out.println(collection); //2.删除元素 // collection.remove(s1);//可以删除成功 // collection.remove(new Student("懒羊羊",10));//不可以删除成功,因为在堆内存中重新开辟了一块空间 // System.out.println("删除之后:"+collection.size()); //3.遍历元素 // } //3.1 使用增强for循环 // for (Object o : collection) { // Student s=(Student)o;//强转成Student类型 // System.out.println(s); //3.2使用迭代器(在不能使用collection的方法进行操作) Iterator it = collection.iterator(); while(it.hasNext()){ Student s=(Student)it.next(); System.out.println("集合中的元素:"+s); } //4.判断 System.out.println(collection.contains(s1)); System.out.println(collection.isEmpty()); } } //学生类 public class Student { public String name; public int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object obj) { //1.判断是否是同一个对象 if (this == obj) return true; //2.判断是否是空 if (obj==null) return false; //3.判断是否是同一个类 if(obj instanceof Student){ Student student = (Student) obj; //4.比较属性 if(this.name.equals(student.getName())&&this.age==student.getAge()){ return true; } } //5.不满足条件就返回false return false; } }
2.3、List子接口
-
特点:有序,有下标,元素可以重复
-
方法:
-
void add(int index,Object o)//在index位置插入对象o.
-
boolean addAll(int index, Collection c)将一个集合中的元素添加到此集合中的index位置
-
Object get (int index)//返回集合中指定位置的元素
-
List subList(int fromIndex , int toIndex)//返回fromIndex和toIndex之间的元素
-
-
代码分析
//List接口的使用 public class Demo03 { public static void main(String[] args) { List list = new ArrayList(); //1.添加元素 list.add("熊大"); list.add("熊二"); list.add("光头强"); System.out.println(list.size()); System.out.println(list.toString()); // //2.删除元素 // list.remove(0);//通过索引删除 // list.remove("光头强");//通过元素删除 // list.clear(); // System.out.println("删除之后:"+list); // 3.遍历元素 // 3.1 既然有下标,可以用for循环 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } //3.2使用增强For循环 for (Object o : list) { String o1 = (String) o; System.out.println(o1); } //3.3使用迭代器 Iterator it = list.iterator(); while(it.hasNext()){ System.out.println("迭代器遍历:"+it.next()); } //3.4使用列表迭代器(与迭代器的区别):可以向前或向后进行元素的遍历,增加,删除,修改 ListIterator lt = list.listIterator(); System.out.println("------从前往后遍历--------"); while(lt.hasNext()){ System.out.println(lt.nextIndex()+":"+lt.next()); } System.out.println("------从后往前遍历--------"); while(lt.hasPrevious()){ System.out.println(lt.previousIndex()+":"+lt.previous()); } //4.判断 System.out.println(list.contains("光头强")); System.out.println(list.isEmpty()); //5.确定位置 System.out.println(list.indexOf("熊大")); } } //list使用二 public class Demo04 { public static void main(String[] args) { List list = new ArrayList(); //1.添加数字数据(自动装箱) list.add(10); list.add(20); list.add(30); list.add(40); list.add(50); System.out.println("元素个数:"+list.size()); System.out.println("元素:"+list.toString()); //2.删除元素 list.remove(0); list.remove((Object)10); list.remove(new Integer(10));//以上三行效果一样 System.out.println("元素个数"+list.size()); System.out.println("删除后元素:"+list.toString()); //3.补充 subList 返回子集合,含头不含尾(左闭右开) List list1 = list.subList(1, 3); System.out.println(list1.toString()); } }
2.4、List实现类
-
ArrayList:
-
数组结构实现,查询快,增删慢
-
JDK1.2版本,运行效率快,线程不安全
-
源码分析:
-
DEFAULT_CAPACITY=10;默认容量
注意:如果没有向集合中添加任何元素时,容量为0;添加一个元素之后,容量10,每次扩容大小是原来的1.5倍
-
elementData:存放元素的数组
-
size:实际元素个数
-
-
-
代码分析
//ArrayList的使用 public class Demo05 { public static void main(String[] args) { //创建集合 size=0,容量0,扩容原来的1.5倍 ArrayList arrayList = new ArrayList(); //1.添加元素 Student s1 = new Student("懒羊羊", 15); Student s2 = new Student("灰太狼", 19); Student s3 = new Student("沸羊羊", 17); arrayList.add(s1); arrayList.add(s2); arrayList.add(s3); System.out.println("元素个数:"+arrayList.size()); System.out.println("元素:"+arrayList.toString()); //2.删除元素 // arrayList.remove(s1); arrayList.remove(new Student("美羊羊",10)); System.out.println("删除之后元素个数:"+arrayList.size()); System.out.println("删除之后:"+arrayList.toString()); //3.迭代器遍历 Iterator it = arrayList.iterator(); while(it.hasNext()){ Student s=(Student)it.next(); System.out.println(s.toString()); } //4. listIterator列表迭代器(注意是先顺序,在逆序,因为要逆序的话,下标要在最后一个元素位置,而顺序遍历之后正好在最后一个元素) ListIterator li = arrayList.listIterator(); System.out.println("-------顺序遍历------"); while (li.hasNext()){ Student s = (Student)li.next(); System.out.println(s); } System.out.println("-------逆序遍历------"); while (li.hasPrevious()){ Student s=(Student)li.previous(); System.out.println(s); } //5.判断 System.out.println(arrayList.contains(s1)); System.out.println(arrayList.contains(new Student("懒羊羊", 15))); System.out.println(arrayList.isEmpty()); //6.查找 System.out.println(arrayList.indexOf(s1)); } }
-
Vector:
-
数组结构实现,查询快,增删慢
-
JDK1.0版本,运行效率慢,线程安全
-
-
代码分析
package Demo2; import java.util.Enumeration; import java.util.Vector; //测试Vector的使用 public class Demo01 { public static void main(String[] args) { //1.创建集合 Vector objects = new Vector(); //2.添加元素 objects.add("天下无贼"); objects.add("贼眉鼠眼"); objects.add("小果叮"); System.out.println(objects.size()); System.out.println(objects.toString()); //3.删除元素 objects.remove(0); objects.remove("天下无贼"); System.out.println("删除之后元素个数:"+objects.size()); System.out.println("删除之后"+objects.toString()); //4.遍历 枚举器 Enumeration en = objects.elements(); while(en.hasMoreElements()){ String s=(String)en.nextElement(); System.out.println(s); } } }
-
LinkedList:
-
双向链表结构实现,增删快,查询慢
-
3、泛型
-
Java泛型是JDK1.5中引入的一个新特性,本质是参数化类型,把类型作为参数化传递。
-
常见形式有泛型类、泛型接口、泛型方法。
-
语法:<T,...> T称为类型占位符,表示一种引用类型,如果编写多个引用类型隔开。
-
好处:提高代码的重用性;防止类型转换异常,提高代码的安全性。
-
泛型类和接口:泛型放在类名和接口之后,而方法是泛型在方法类型前面。
-
代码分析
/** * 泛型类(在实例化时给出具体类型) */ public class MyGeneric<T> { //使用泛型T //1.创建变量 T t; //2.泛型作为方法的参数 public void show(T t){ System.out.println(t); } //3.泛型作为方法的返回值 public T getT(){ return t; } } /** * 泛型方法 * 方法里面不能创建对象,可以将t的值赋给一个变量 */ public class myGenericMethod { public <T>T show(T t){ System.out.println(t); return t; } } /** * 泛型接口,在实现类中给出具体类型 * 语法:接口名<T> * 不能泛型静态常量 */ public interface MyInterface<T> { String name="欧阳小峰"; Integer age=18; //以泛型作为返回值的方法,其中参数类型也是泛型 T server(T t); } //接口实现类 public class MyInterfacelmpl implements MyInterface<String> { @Override public String server(String s) { System.out.println(s); return s; } } class MyInterfacelmpl2<T> implements MyInterface<T> { @Override public T server(T t) { System.out.println(t); return t; } } /** * 测试泛型 * 注意:泛型只能使用引用类型,不同泛型对象之间不能相互赋值 */ public class TestGeneric { public static void main(String[] args) { //使用泛型类创建对象 //字符串类型 MyGeneric<String> myGeneric = new MyGeneric<String>(); myGeneric.t="菠萝吹雪"; myGeneric.show("果宝机甲"); String string= myGeneric.getT(); //整型 MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>(); myGeneric2.t=110; myGeneric2.show(119); Integer integer= myGeneric2.getT(); //测试泛型接口 MyInterfacelmpl mi = new MyInterfacelmpl(); mi.server("shenyan"); //测试泛型方法 /** * 其实这里不难发现,泛型有模板的功能 */ myGenericMethod myGenericMethod = new myGenericMethod(); myGenericMethod.show("我爱s丫头"); myGenericMethod.show(20200329); } }
泛型集合
-
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
-
特点:
-
编译时即可检查,而非运行时抛出异常
-
访问时不必类型转换(拆箱)
-
不同泛型之间引用不能相互赋值,泛型不存在多态。
-
-
4、Set集合
Set实现类
-
HashSet:
-
基于HashCode计算元素存放位置
-
当存入元素的哈希码相同时,会调用equals进行确认,如结果为true则拒绝后者存入
-
代码分析
/** * hashSet的使用 * 存储结构:哈希表(数组+链表+红黑树) * 补充:泛型使用Person时,创建集合HashSet<Person> hashSet = new HashSet(); 添加元素add(new Person()),里面的参数和之前的重复, * 也可以添加到集合里,涉及到堆内存 */ import java.util.HashSet; import java.util.Iterator; public class Demo01 { public static void main(String[] args) { HashSet<String> hashSet = new HashSet(); //1.添加 hashSet.add("唐三"); hashSet.add("小舞"); hashSet.add("戴沐白"); hashSet.add("马红骏"); System.out.println("元素个数:"+hashSet.size()); System.out.println(hashSet.toString()); //2.删除 hashSet.remove("唐三"); System.out.println(hashSet.toString()); //3.遍历 System.out.println("-------增强for------"); for (String s : hashSet) { System.out.println(s); } System.out.println("-------迭代器------"); Iterator<String> iterator = hashSet.iterator(); while(iterator.hasNext()){ String s=iterator.next(); System.out.println(s); } //4.判断 System.out.println(hashSet.contains("小舞")); System.out.println(hashSet.isEmpty()); } } /** * hashSet使用 * 存储过程 * 堆内存中 * 1.根据hashCode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步 * 2.根据equals方法,如果返回为true,则认为重复,否则形成链表 */ public class Demo02 { public static void main(String[] args) { //1.创建集合 HashSet<Person> person = new HashSet(); //2.添加元素 Person p1 = new Person("李星云", 18); Person p2 = new Person("姬如雪", 17); Person p3 = new Person("袁天罡", 300); person.add(p1); person.add(p2); person.add(p3); person.add(new Person("姬如雪",17));//会添加成功到集合中 //当在Person类中重写了hashCode和equals方法,这时元素重重复,就添加不进去啦 System.out.println("元素个数:"+person.size()); System.out.println(person.toString()); } }
-
-
TreeSet:
-
基于排序顺序实现元素不重复
-
实现了SortedSet接口,对集合元素自动排序
-
元素对象的类型必须实现Comparable接口,指定排序规则
-
通过CompareTo方法确定是否为重复元素。
-
代码分析
/** * 使用TreeSet保存数据 * 存储结构:红黑树 * 要求:元素必须要实现Comparable接口,否则会报异常ClassCastException,comparaTo()方法返回值为0,认为是重复元素 */ public class Demo03 { public static void main(String[] args) { //1.创建集合 TreeSet<Person> person = new TreeSet(); //2.添加元素 Person p1 = new Person("李星云", 18); Person p2 = new Person("姬如雪", 17); Person p3 = new Person("袁天罡", 300); person.add(p1); person.add(p2); person.add(p3); System.out.println("元素个数:"+person.size()); System.out.println(person.toString()); } } /** * TreeSet集合的使用 * Comparator:实现定制比较(比较器) * 要求:使用TreeSet集合实现字符串按照长度进行排序 */ public class Demo04 { 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; } }); //添加元素 Person p1 = new Person("李星云", 18); Person p2 = new Person("雪儿", 25); Person p3 = new Person("术士袁天罡", 300); persons.add(p1); persons.add(p2); persons.add(p3); System.out.println("元素个数:"+persons.size()); System.out.println(persons.toString()); } } //Person类 public class Person implements Comparable<Person>{ public String name; public int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Person o) { //先按姓名比,然后再按年龄比 int n1=this.getName().compareTo(o.getName()); int n2=this.age-o.getAge(); return n1==0?n2:n1; } // //重写hashCode方法 // @Override // public int hashCode() { // int n1=this.name.hashCode(); // int n2=this.age; // return n1+n2; // } // //重写equals方法 // // @Override // public boolean equals(Object obj) { // //1.判断是否是同一个对象 // if(this==obj){ // return true; // } // //2.判断obj是否为空 // if(obj==null){ // return false; // } // //3.判断obj是否是Person类(是否是同一个类) // if(obj instanceof Person){ // Person p=(Person)obj; // //判断是否相等 // if(this.name.equals(p.getName())&&this.age==p.getAge()){ // return true; // } // } // //5.不满足条件直接返回false // return false; // } //编辑器自带的重写方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, age); } } /** * 要求:使用TreeSet集合实现字符串按照长度进行排序 */ public class Demo05 { public static void main(String[] args) { //创建集合 并指定比较规则 TreeSet<String> string = new TreeSet(new Comparator<String>() { @Override public int compare(String s1, String s2) { int n1=s1.length()-s2.length(); int n2=s1.compareTo(s2); return n1==0?n2:n1; } }); //添加元素 string.add("shenyan"); string.add("shen"); string.add("yan"); string.add("sy"); System.out.println("元素个数:"+string.size()); System.out.println(string.toString()); } }
-
5、Map集合
-
Map接口的特点:
-
用于存储任意键值对(Key-Value)
-
键:无序、无下标、不允许重复
-
值:无序、无下标、允许重复
-
Map父接口
-
特点:存储一对数据(Key-Value),无序无下标,键不可重复,值可重复
-
方法:
-
V put(K key, V value);//将对象存入到集合中,关联键值。key重复则覆盖原值;
-
Object get(Object key);//根据键获取相应的值
-
Set<K>;//返回所有Key;
-
Collection<V> values();//返回包含所有值得Collection集合
-
Set<Map.Entry<>K,V> //键值匹配的Set集合
-
代码分析
/** * Map接口的使用 * 特点:存储键值对,键不能重复,值可以重复,无序 */ public class Demo01 { public static void main(String[] args) { //创建Map集合 Map<String, String> map = new HashMap<>(); //1.添加元素 map.put("海神","唐三"); map.put("修罗神","唐三"); map.put("天使神","千任雪"); map.put("食神","奥斯卡"); System.out.println("神位:"+map.size()); System.out.println(map.toString()); //2。删除 map.remove("海神"); System.out.println("删除之后:"+map.toString()); //遍历 // 3.1使用keySet(); System.out.println("-----使用KeySet------"); Set<String> keySet = map.keySet(); for (String s : keySet) { System.out.println(s+"---"+map.get(s));//根据键获得值 } //3.2 使用entrySet()方法 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(map.containsKey("海神")); System.out.println(map.containsValue("奥斯卡")); } }
-
Map集合的实现类
-
HashMap:
-
JDK1.2版本,线程不安全,运行效率快,允许用null作为key或是value
-
存储结构:哈希表
-
重复依据:键的hashCode()方法和equals方法
-
源码分析
-
代码分析
/** * HashMap集合的使用 * 存储结构:哈希表(数组+链表+红黑树) */ public class Demo02 { public static void main(String[] args) { //创建集合 HashMap<Student, String> student = new HashMap<>(); //添加元素 Student s1 = new Student("熊大", 19); Student s2 = new Student("熊二", 15); Student s3 = new Student("涂涂", 6); student.put(s1,"狗熊岭"); student.put(s2,"狗熊岭的树洞"); student.put(s3,"光头强家"); student.put(new Student("涂涂",6),"光头强家");//在没有重写方法之前是可以添加到集合进去的 //重写了hashCode和equals方法之后是不可以添加进去相同的元素的额 System.out.println("狗熊玲成员:"+student.size()); System.out.println(student.toString()); //删除 student.remove(s1); System.out.println("删除之后:"+student.size()); System.out.println(student.toString()); //遍历 //3.1使用keyset方法 System.out.println("-----使用keyset-----"); for (Student stu : student.keySet()) { System.out.println(stu.toString()+"---"+student.get(stu)); } //3.2使用entrySet方法 System.out.println("-------使用entrySet------"); for (Map.Entry<Student, String> stu : student.entrySet()) { System.out.println(stu.getKey()+"----"+stu.getValue()); } } }
-
-
HashTable:
-
线程安全,运行效率慢,不允许null作为key或是value
-
-
Properties:
-
HashTable的子类,要求key和value都是String,通常用于配置文件的读取
-
-
TreeMap:
-
实现了SortedMap接口(是Map的子接口),可以对key自动排序
-
存储结构:红黑树
-
6、Collection工具类
-
概念:集合工具类,定义了除了存取以外的集合常用方法
-
方法:
-
reverse()//反转
-
shuffle()//随机打乱元素顺序
-
sort()//升序排序(元素类型必须实现Comparable接口)
-
-
代码分析
/** * Collection工具类的使用 */ public class Demo03 { public static void main(String[] args) { //创建集合 List<Integer> list = new ArrayList<>(); //添加元素 list.add(56); list.add(12); list.add(78); list.add(51); list.add(42); list.add(33); //sort排序 System.out.println("排序前:"+list.toString()); Collections.sort(list); System.out.println("排序后:"+list.toString()); //二分查找 binarySearch int i= Collections.binarySearch(list,13); System.out.println(i); //copy复制 List<Integer> dest = new ArrayList<>(); for (int k = 0; k < list.size(); k++) { dest.add(0); } Collections.copy(dest,list); System.out.println(dest.toString()); //reverse反转 Collections.reverse(list); System.out.println("反转之后:"+list); //shuffle打乱 Collections.shuffle(list); System.out.println("打乱之后:"+list); //补充: //list转成数组 Integer[] arr = list.toArray(new Integer[10]); System.out.println(arr.length); System.out.println(Arrays.toString(arr)); //数组转成集合 String[] names={"张三","李四","王五"}; //集合是一个受限集合,不能添加和删除 List<String> list2 = Arrays.asList(names); //list2.add("赵六"); System.out.println(list2); //把基本类型数组转换成集合时,需要修改为包装类型 Integer[] nums={100,2354,45454}; List<Integer> ints = Arrays.asList(nums); System.out.println(ints); } }