七、集合框架,Collection、list、set、map老师说集合学好了走到哪里都不怕
集合框架
1. 数组
对象数组
题目:将全班30位同学的信息,一次录入(增加)到一个对象数组之中,并且输出。
分析:
类:Student(学生类):name,age
StudentBiz(学生数组类):Student[] students = new Student[30];
对象数组有自己的不足
- 数组的长度固定,不可改变
- 数组无法求出真实有效的数据个数
- 用数组实现对象的增删改查操作比较发麻烦
2.collection集合
Collection->List/Set
List---->ArrayList/LinkedList
Set---->HashSet/TreeSet
Collection 是一个接口,允许有重复的元素,而另一些不允许。一些cottection是有序的(输入顺序是否和输出顺序一致),而另一些是无序的
- 用集合实现对象的额增删改查很方便,直接调用add()方法即可
- Collection长度会自动适应不必要人工干预
- Collection可以获取到真实的数据个数
collection集合方法
2.1add方法
增加字符串
// Collection coll = new Collections();//接口不能被实例化
//add(Object a ):向集合中增加一个元素
Collection coll = new ArrayList();
coll.add("a");
coll.add("b");
coll.add("c");
System.out.println(coll);//重写了toString方法.要不然直接打印内存地址
//[a, b, c]
增加数组
Collection coll = new ArrayList();
//增加对象
Student stu1 = new Student();
stu1.setName("张三");
stu1.setAge(23);
Student stu2 = new Student();
stu2.setName("李四");
stu2.setAge(24);
Student stu3 = new Student();
stu3.setName("王五");
stu3.setAge(15);
coll.add(stu1);
coll.add(stu2);
coll.add(stu3);
//重写Student中的toString方法
System.out.println(coll);
//[张三-23, 李四-24, 王五-15]
2.2clear方法
移除此Collection中的所有元素
coll.clear();//clear:清楚集合中所有的元素
System.out.println(coll);
2.3size方法
//求集合中真实数据的个数:size()
System.out.println(coll.size());
2.3addAll方法
Collection coll = new ArrayList();
coll.add("a");
coll.add("b");
coll.add("c");
Collection col2 = new ArrayList();
col2.add("c");
col2.add("d");
col2.add("e");
//addAll:可以将一个集合中的全部元素增加到另一个集合之中
coll.addAll(col2) ;
System.out.println(coll);
//a b c c d e
2.4containsAll/contains方法
如果此collection包含指定collection中的所有元素,则返回true
//判断集合是否包含了指定的对象(元素)
boolean flag = coll.contains("a");
System.out.println(flag);
//-------
boolean flag1 = coll.contains(stu1);
System.out.println(flag1);
//containsAll:判断集合是否包含了另一个集合
boolean flag2= coll.containsAll(col2);
System.out.println(flag2);
//true
//true
//true
2.5isEpty方法
如果此collection不包含元素,则返回true
Collection coll = new ArrryList();
boolean flag = coll.isEmpty();
System.out.println(flag);
//true
2.6iterator方法(重点掌握)
//iterator():迭代器
System.out.println("col2:"+col2);
Iterator iter = col2.iterator();
// iter.hasNext();//判断集合是否有下一个元素
while(iter.hasNext()){
//接收类型为Object强制转换成String
String reault = (String)iter.next();//取出下一个元素
System.out.println(reault);
2.7 remove/removeAll方法
//remove:可以删除集合之中指定的对象
col2.remove("b");
System.out.println(col2);
//removeAll:从一个集合之中删除另一个集合中包含的元素
coll.removeAll(col2);
2.8 retinAll方法
//retainAll:与removeAll是相反操作,从一个集合之中只保留另一个集合的所有元素
Collection col1 = new ArrryList();
coll.add("a");
coll.add("b");
coll.add("c");
Collection col2 = new ArrryList();
col2.add("a");
col2.add("c");
System.out.println("col1"+col1);
System.out.println("col2"+col2);
coll.retainAll(col2);
System.out.println("col1"+col1);
ystem.out.println("col2"+col2);
//abc
//ac
//ac
//ac
2.9toArray方法
//toArray():将集合转换为数组(Obiect[]);
Object[] col1Array = coll.toArray();
System.out.println(col1Array[0]);
System.out.println(col1Array[1]);
3.List集合方法
-----ArrayList的特有方法
3.1 add()插入到指定位置
List list1 = new ArrayList();
list1.add("a");
list1.add("b");
list1.add("c");
System.out.println(list1);
list1.add("d");
System.out.println(list1);
//List接口中,有一个重载的add()方法,可以将增加的元素指定到某一个具体的位置
list1.add(1,"e");
System.out.println(list1);
3.2 addAll方法插入
List list1 = new ArrayList();
list1.add("a");
list1.add("b");
list1.add("c");
List list2 = new ArrayList();
list2.add("1");
list2.add("2");
//可以将增加的集合元素指定到某一个具体的位置
list1.addAll(2,list2);
System.out.println(list1);
3.3 get方法
List list1 = new ArrayList();
list1.add("a");
list1.add("b");
//通过get方法获取到集合中的某一个元素(类似于数组的下表)
Object o = list1.get(1);
System.out.println(o);
//b
3.4 indexof/lastindexof方法
List list1 = new ArrayList();
list1.add("a");
list1.add("b");
list1.add("c");
//可以获取到某一个指定对象(元素)在集合之中的位置
int e = list1.indexOf("b");
System.out.println(2);
//1
//从后往前找
int e1 = list1.lastIndexOf("c");
System.out.println(e1);
//3
3.5 remove方法
list1.remove("a");
System.out.println(list1);
list1.remove("e");
System.out.println(list1);
//可以删除指定索引位置对象(元素)通过索引删除(重载方法)(因为list集合是有序的)
list1.remove(1);
System.out.println(list1);
3.6 set方法
//将指定位置的元素(对象)修改成新的
list1.set(3,"中");
System.out.println(list1);
3.7 sublist方法
//类似subString(),截取List集合,左闭右开
List list = list1.subList(2, 4);
System.out.println(list);
------LinkedList的特有方法
3.8 addList/addFirst方法
LinkedList list = new LinkedList();
list.add("hello");
list.add("world");
list.addLast("wh");
list.addFirst("hw");
System.out.println(list);
-----ArrayList和LinkedList区别
arrayList(动态数组)
优点:每个元素紧密相连,可以通过下表快速取存
缺点:增删改麻烦,覆盖
linkedList(链式)
缺点:查询麻烦
优点:增删改方便
-----Collection、List、Set区别
Collection:存储的数据是 不唯一、无序的对象
List:存储的数据是 不唯一、有序的对象
Set:存储的数据是 唯一、无序的对象
集合 | 存储数据是否唯一 | 是否有序 |
---|---|---|
Collection | 不唯一 | 无序 |
List | 不唯一 | 有序 |
Set | 唯一 | 无序 |
唯一:不能重复
有序:不是排序;是输入顺序 是否与 输出顺序一致的。
是否唯一(因为Collection是抽象类所以实现不了,此处用Collection和List对比)
public static void main(String[] args) {
Collection list = new ArrayList();
list.add("aa");
list.add("aa");
list.add("bb");
System.out.println(list);
Collection set = new HashSet();
set.add("aa");
set.add("aa");
set.add("cc");
System.out.println(set);
}
//[aa, aa, bb]
//[aa, cc]
//可以看出在HashSet中不能存在重复的值只能是唯一的所以add了两个aa只显示了一个而ArrayList是不唯一的
是否有序
public static void main(String[] args) {
Collection list = new ArrayList();
list.add("中国");
list.add("俄罗斯");
list.add("美国");
System.out.println(list);
Collection set = new HashSet();
set.add("中国");
set.add("俄罗斯");
set.add("美国");
System.out.println(set);
}
//[中国, 俄罗斯, 美国]
//[美国, 俄罗斯, 中国]
//可以看出ArrayList是按顺序输出的是有序的,而HashSet是无序的
4.Map集合方法
key:唯一
value:不唯一
类 | 返回值 |
---|---|
Collection中的类(List、Set) | 删除的返回值是boolean |
Map中的类 | 是根据Key删除,返回值是value |
4.1 Map常用方法
HashMap map = new HashMap();
map.put("s01","张三");//key:学号, value:姓名
map.put("s02","李四");//key:学号, value:姓名
map.put("s03","王五");//key:学号, value:姓名
System.out.println(map);
Object v = map.get("s01");//根据key找value
System.out.println(v);
int size = map.size();
System.out.println(size);//元素的个数
boolean s01 = map.containsKey("s01");
System.out.println(s01);//判断是否包含了指定的key
//keySet方法将Map转为单值集合
//转为只包含Key的单值集合
Set set = map.keySet();//为什么是set不是list?因为map中key是唯一的
System.out.println(set);
//转化为只包含value的单值集合
//values方法转换单值valuse
Collection values = map.values();
System.out.println(values);
map.remove("s01");//删除,通过学号/删除成功返回值,就是删除的value对象,删除没成功不提示
System.out.println(map);
4.2 如何遍历集合
- 循环for(普通for(不适用无序的集合),增强for(建议使用增强for))
- 迭代器
public interface Iterator<E>{
...}
4.2.1 List
- 循环for
List list = new ArrayList();
list.add("aa");
list.add("bb");
list.add("cc");
for (int i = 0; i <list.size() ; i++) {
System.out.println(list.get(i));
}
- 增强for
List list = new ArrayList();
list.add("aa");
list.add("bb");
list.add("cc");
for (Object lists:list) {
System.out.println(lists);
}
- 迭代器
List list = new ArrayList();
list.add("aa");
list.add("bb");
list.add("cc");
Iterator iterator = list.iterator();
while(iterator.hasNext()){
Object o = iterator.next();
System.out.println(o);
}
4.2.2 Set
- 循环for
不能使用for因为Set是无序的没有下标
- 增强for
Set set = new HashSet();
set.add("AA");
set.add("BB");
set.add("CC");
for (Object sets :set) {
System.out.println(sets);
}
- 迭代器
Set set = new HashSet();
set.add("AA");
set.add("BB");
set.add("CC");
Iterator iterator = set.iterator();
while(iterator.hasNext()){
Object o = iterator.next();
System.out.println(o);
}
4.2.3 Map(将双值,转化单值集合)
- 循环for
不能使用for因为Set是无序的没有下标
- 增强for
Map map = new HashMap();
map.put("s01","zs");
map.put("s02","ls");
map.put("s03","ww");
Set set1 = map.keySet();
for(Object O:set1){
System.out.println("key:"+O);
//value可以不用迭代器,可以用get方法,通过key找到value
//Object v = map.get(O);
// System.out.println("value:"+v);
}
//====================================================
Collection values = map.values();
for(Object value:values){
System.out.println(value);
}
- 迭代器
Map map = new HashMap();
map.put("s01","zs");
map.put("s02","ls");
map.put("s03","ww");
Set set1 = map.keySet();
Iterator iterator = set1.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
Collection values = map.values();
Iterator iterator1 = values.iterator();
while(iterator1.hasNext()){
System.out.println(iterator1.next());
}
- entry遍历
Map map = new HashMap();
map.put("s01","zs");
map.put("s02","ls");
map.put("s03","ww");
Set entries = map.entrySet();
for(Object e :entries){
Map.Entry et = (Map.Entry)e;
Object k = et.getKey();
Object v = et.getValue();
System.out.println("k-"+k);
System.out.println("v-"+v);
}
5.泛型
Collection、Map都能用
自从jdk1.5开始的
作用:
- 保证数据安全
List<String> list = new ArrayList<String>();
list.add("aa");
list.add(2);//这句话报错,表明只能输入String类型
for (Object lists:list) {
System.out.println(lists);
}
- 防止类型转换时出错
list.add(默认是Object)、二u过加了Double泛型,则自动编程list.add(double…),返回值类型,会直接返回double类型的数据
简言,以Double泛型为例,入伙不加泛型,则默认操作的是Object类型,如果加了Double泛型,则默认操作的是Double类型。
使用
//单值
// List<String> list = new ArrayList<String>();
List<String> list = new ArrayList<>(); // 和上面的等价/1.7之后提供的类型推断
list.add("a");
String s = list.get(0);
System.out.println(s);
//双值
//k(学号) ,v(名次)
Map<String,Integer> map = new HashMap<>();
map.put("s01",3);
map.put("s02",1);
map.put("s03",2);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for(Map.Entry<String, Integer> o:entries){
System.out.println(o.getKey());
System.out.println(o.getValue());
}
//迭代器也能用泛型方式
//取key
Set<String> keys = map.keySet();
Iterator<String> iterator = keys.iterator();
while(iterator.hasNext()){
String key = iterator.next();
Integer value = map.get(key);
System.out.println(key+"--"+value);
}
示例:根据人的名字,查询这个人的全部信息
Map<String,Person> map = new HashMap<>();
Person per01 = new Person("zs",23,"西安");
Person per02 = new Person("ls",23,"北京");
Person per03 = new Person("ww",25,"上海");
Person per04 = new Person("zl",24,"天津");
Person per05 = new Person("sq",27,"深圳");
//key 名字 ,value:人
map.put("zs",per01);
map.put("ls",per02);
map.put("ww",per03);
map.put("zl",per04);
map.put("sq",per05);
System.out.println("请输入人的名字");
Scanner input = new Scanner(System.in) ;
String name = input.next();
//map方法简单
Person person = map.get(name);
System.out.println(person);
//如果对象不是Null,在打印时会调用toString.如果是null则不会调用toString
//老方法底层
// Set<String> names = map.keySet();
// //在Names中找name
// for(String n:names){
// if(n.equals(name)){
// Person person = map.get(n);
// System.out.println(person);
// }
// }
集合工具类
集合工具类Collections(集合)
List<String> list = new ArrayList<>();
list.add("a");
list.add("e");
list.add("w");
list.add("v");
list.add("s");
//字典顺序排序
Collections.sort(list);
System.out.println(list);
//获取集合最大值、最小值
String max = Collections.max(list);
System.out.println(max);
String min = Collections.min(list);
System.out.println(min);
//二分查询(在list中找v的索引)(使用前,必须保证集合元素是自然有序的,sort)
int v = Collections.binarySearch(list, "v");
System.out.println(v);
//混洗,打乱已有顺序
Collections.shuffle(list);
//反转、倒序
Collections.reverse(list);
//换顺序
Collections.swap(list,2,3);
//替换
Collections.replaceAll(list, "a", "A");
//将所有元素全部填充
Collections.fill(list,"H");
数组工具类Arrays(数组)
int[] arr = new int[]{
2,4,5,8,6,1};
//排序
Arrays.sort(arr);
for (int i = 0; i <arr.length ; i++) {
System.out.print(arr[i]+"\t");
}
System.out.println();
//二分法找数字(返回下表)(先有序)
int i1 = Arrays.binarySearch(arr, 5);
System.out.println(i1);
System.out.println();
//数字全部填充为5
Arrays.fill(arr,5);
for (int i = 0; i <arr.length ; i++) {
System.out.print(arr[i]+"\t");
}
比较器
list.add(3) ; //2 4 3 1 9
list.add(“b”) ; //b c a d w
Collections.sort(list) //能够识别一些自然顺序
但是,如果集合中的元素是 用户自定义对象,如何排序?
Person p1 = new Person(3,“zs”,23,6) ;
Person p2 = new Person(2,“ls”,24,2) ;
Person p3 = new Person(1,“ww”,25,8) ;
list.add(p1);
list.add(p2);
list.add(p3);
Collections.sort(list) //程序 无法知道 ,是根据什么排序? ->自定义比较器, 自定义“比较时,根据学号排”
自定义比较器:Comparable 、Comparator
Comparable: 内部比较器(侵入性,需要修改原有代码)
package col;
/* * Created by 颜群 */
public class Person implements Comparable{
private int id ;
private String name ;
private int age ;
private String city;
public Person() {
}
public Person(int id, String name, int age, String city) {
this.id = id;
this.name = name;
this.age = age;
this.city = city;
}
public Person( String name, int age, String city) {
this.name = name;
this.age = age;
this.city = city;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", city='" + city + '\'' +
'}';
}
//重写比较器接口中的方法
@Override
public int compareTo(Object o) {
//Obiect转换成Person
Person input = (Person)o;
//根据学号 降序 3,2,1
int result = this.id > input.id? -1:( this.id == input.id?0:1);
//如果学号相同根据姓名升序
if(result == 0 ){
//调用String已经重写过的compareTo本身就是升序/如果想要降序在前面加负号
result = -this.name.compareTo( input.name) ;
}
return result;
}
}
思路:将比较的对象(Person)实现Comparable接口,重写连的compareTo()方法。在compareTo()中编写比较的逻辑。重点是返回值,-1 ,0,1 ;
Comparator:外部比较器 (无侵入性,不影响原有代码)
1.先定义一个外部比较器
package col;
import java.util.Comparator;
public class MyComparatorWithId implements Comparator {
@Override
public int compare(Object o1, Object o2) {
//先转换
Student s1 = (Student)o1 ;
Student s2 = (Student)o2 ;
return s2.getId() - s1.getId() ;
}
}
2.使用外部比较器
package col;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
//内部比较器
public class Demo08 {
public static void main(String[] args) {
Student s1 = new Student(10,"zs",23,"xa") ;
Student s2 = new Student(2,"zs",26,"xa") ;
Student s3 = new Student(3,"zs",24,"xa") ;
List<Student> students = new ArrayList<>() ;
students.add(s1);
students.add(s2);
students.add(s3);
Collections.sort(students,new MyComparatorWithId() );
//给students使用了MyComparatorWithId比较器
System.out.println(students);
}
}
List list = new ArrayList<>() ;
包装类(自动装箱、自动拆箱)
evething is an Object,万物皆对象。 属性、方法
自动装箱:基本类型 ->包装类型 ,int ->Integer(有更多的属性和方法)
自动拆箱:包装类型->基本类型,Integer ->int
java中 将8个基本类型,包装成了8个对象类型(引用类型)。这8个对象类型 就成为包装类
package col;
public class BZL {
public static void main(String[] args) {
int i = 10 ;
Integer j = new Integer(20) ;
i = j ;//Integer->int 自动拆箱 底层用的是intValue()
j = i ;
//int ->Integer 自动装箱 底层用的是valueOf() ,该方法中有个缓冲区 [-128,127],
//如果要装箱的数字 在缓冲区范围以内,则直接从缓冲区中取;否则,new Integer()一个新对象
Integer i1 = 100 ;
Integer i2 = 100 ;
//因为100在缓冲区以内所以从缓冲区拿100是同一个对象。所以为true
Integer i3 = 1000 ;
Integer i4 = 1000 ;
//因为1000大于缓冲区所以new了两个Integer而对象类型对比的是引用是否为同一个
System.out.println(i1 == i2);//true
System.out.println(i3 == i4);//false
}
}
面试题
面试题
- set中的remove()为什么只能根据内容删除?不能根据下表删除?
因为set是无序的没有下标
- 当Map中的key转换成单值时为什么系统转换成了set?
因为map中的key是唯一的,set也是唯一的(二者匹配)