集合框架
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也是唯一的(二者匹配)

京公网安备 11010502036488号