2.集合笔记

1. Collection接口

在这里插入图片描述

①引入集合

  • 集合和数组都是容器
  • 集合:长度可变,存储对象且对象的类型可以不同
  • 数组:长度固定,存储对象或基本数据类型但都是同类型元素
		//存放person类对象,一旦创建,运行期间长度不可以发生改变
        Person[] array = new Person[3];
      	....		

②Collection接口公共方法

  • Collection是单列集合中的最顶层的接口,接口中的方法可以被所有单列集合使用
      	public boolean add(E e)
	    public void clear() 
      	public boolean remove(E e)
      	public boolean contains(E e)
      	public boolean isEmpty()
      	public int size()
      	public Object[] toArray() //集合元素——>数组

     	Collection<String> coll = new ArrayList<>();
        System.out.println(coll);// []
         
        Collections.addAll(coll,"林俊杰","周杰伦","孙燕姿","五月天","泽野弘之")
        System.out.println(coll); //[林俊杰, 周杰伦, 孙燕姿, 五月天, 泽野弘之, 夏目贵志]

        coll.remove("泽野弘之");//true
     	coll.contains("孙燕姿");//true
        coll.isEmpty();//false
       	coll.size());//5
       	coll.clear();//清空集合元素,只保留集合本身 []

        //public Object[] toArray(): 把集合中的元素,存储到数组中。
        Object[] arr = coll.toArray();
        

③Collections接口工具类方法

		public static <T> boolean addAll(Collection<T> c, T... lements)
		public static void shuffle(List<?> list) 

		//静态方法,可以用接口直接调用
 		ArrayList<String> list = new ArrayList<>();       
        Collections.addAll(list,"a","b","c","d","e"); 
        //[a, b, c, d, e]
        Collections.shuffle(list);
        //[b, d, c, a, e]      

④Comparable接口 Integer+ Person

		public static <T> void sort(List<T> list) //按默认规则排序
		public interface Comparable<T> { public int compareTo(T o); }

Integer

		1.Integer类实现该接口并重写了接口中的抽象方法compareTo
		public final class Integer implements Comparable<Integer>
		public int compareTo(Integer anotherInteger) { ... }

		ArrayList<Integer> list01 = new ArrayList<>();
        Collections.addAll(list01,1,3,2); //[1, 3, 2]
        Collections.sort(list01);//默认是升序 [1, 2, 3]

		ArrayList<String> list02 = new ArrayList<>();
		Collections.addAll(list02,"a","c","b");//[a, c, b]
		Collections.sort(list02);//默认是升序[a, b, c]

Person

  • 分析:Person类必须要实现Comparable接口并重写compareTo方法才能排序
        ArrayList<Person> list03 = new ArrayList<>();
        list03.add(new Person("张三",18));
        list03.add(new Person("李四",20));
        list03.add(new Person("王五",15));
       	
       	//重写前:按输入顺序输出
        [Person{name='张三', age=18}, Person{name='李四', age=20}, Person{name='王五', age=15}]
		
		//重写后:按年龄升序顺序输出
        Collections.sort(list03);
        [Person{name='王五', age=15}, Person{name='张三', age=18}, Person{name='李四', age=20}]
		
		public class Person implements Comparable<Person>{
			...
   			@Override
   			public int compareTo(Person o) {       
        	//自定义规则,比较年龄(this,参数Person)
        		return this.getAge() - o.getAge();//年龄升序排序
    		}
		}

⑤Comparator接口 Intege+ Student

		public static <T> void sort(List<T> list,Comparator<? super T>) //自定义规则排序。
		public interface Comparator<T> {//抽象接口
				int compare(T o1, T o2);
				boolean equals(Object obj);
		}

Integer

		ArrayList<Integer> list01 = new ArrayList<>();
       	Collections.addAll(list01,1,3,2); //[1, 3, 2]
		
		Comparator<Integer> com = new Comparator<Integer>() {
            @Override //重写比较的规则
            public int compare(Integer o1, Integer o2) {
                return o1-o2;//升序
            }
        }	
			
        Collections.sort(list01,com);
        System.out.println(list01);//[1, 2, 3]

Student

	public class Student{
		...
		@Override
		toString
		}
		
		ArrayList<Student> list02 = new ArrayList<>();
        list02.add(new Student("a迪丽热巴",18));
        list02.add(new Student("古力娜扎",20));
        list02.add(new Student("杨幂",17));
        list02.add(new Student("b杨幂",18));      
		//按输入顺序,输出
        
        //仅年龄比较
		Comparator<Student> com = new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //按照年龄升序排序
                return o1.getAge()-o2.getAge();
            }
        }
		
        Collections.sort(list02,com);
	
	
		//带姓名一起
        Collections.sort(list02, new Comparator<Student>() {@Override
            public int compare(Student o1, Student o2) {
                //按照年龄升序排序
                int result =  o1.getAge()-o2.getAge();
                //如果两个人年龄相同,再按首字母升序
                if(result==0){ result =  o1.getName().charAt(0)-o2.getName().charAt(0);}
                return  result;
            }

        });

       //[Student{name='杨幂', age=17}, Student{name='a迪丽热巴', age=18}, Student{name='b杨幂', age=18}, Student{name='古力娜扎', age=20}]
    }

⑥Iterator接口

  1. Iterable接口定义了接口Iterator
  2. Collection接口继承了接口Iterable
		public interface Iterable<T> {
    		Iterator<T> iterator();
    	}
		public interface Collection<E> extends Iterable<E>{
     		Iterator<E> iterator();	//返回迭代器实现类对象     
    	}

		/*
        1.使用Iterator接口接收Collection中方法iterator()返回的实现类对象
        2.使用Iterator接口中的方法hasNext判断下一个(-1)
        3.使用Iterator接口中的方法next取出下一个
		*/
		
        Collection<String> coll = new ArrayList<>();
        Collections.addAll(coll,"姚明","科比","麦迪","詹姆斯","艾弗森");
        
        Iterator<String> it = coll.iterator();//多态     
        while(it.hasNext()){
            String e = it.next();
            System.out.println(e);
        }
        
        String s = it.next();//空集合,取元素就抛出NoSuchElementException
    }
}
  1. Iterator接口原理
    4)迭代器原理

⑦增强for

  • foreach遍历集合和数组:底层使用迭代器
		Collection<E>extends Iterable<E>:
		public interface Iterable<T>谁实现该接口,谁就能使用 "foreach"     
   
    	for(集合/数组的数据类型 变量名: 集合名/数组名)
        	sout(变量名);       
 		 int[] arr = {1,2,3,4,5};
         for(int i:arr)
            System.out.println(i);
    
         ArrayList<String> list = new ArrayList<>();
         Collections.addAll(list,"aaa","bbb","ccc","ddd");
            for(String s : list)
                System.out.println(s);
                                             

1.1 List接口

		public interface List< E > extends Collection< E > 

①List接口特点

  1. 有序,存取一致
  2. 有索引,包含索引方法
  3. 允许重复

②List接口中带索引的方法

        - public void add(int index, E element) 
        - public E get(int index)
        - public E remove(int index)
        - public E set(int index, E element)
    注意:
        操作索引的时候,要防止索引越界异常
        IndexOutOfBoundsException:集合索引越界异常
        ArrayIndexOutOfBoundsException:数组索引越界异常
        StringIndexOutOfBoundsException:字符串索引越界异常

③List接口的3种遍历方法

 		for (String s : list)
        	System.out.println(s);
       
      	Iterator<String> it = list.iterator();//获取迭代器对象
    	while(it.hasNext()){
        	String s = it.next();
        	System.out.println(s);
    	}

    	for(int i=0; i<list.size(); i++){
        	String s = list.get(i);
        	System.out.println(s);
    	}

④List接口实现类ArrayList-多线程

public class ArrayList< E >  implements List< E > 

分析

  • ArrayList底层是由数组实现,所以适合查询、遍历,不适合增删。因而
  • ArrayList包含大量的索引方法!
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list); //[] 直接打印得到的不是地址,而是内容
       
      	Collections.addAll(list,"赵丽颖","迪丽热巴","古力娜扎","玛尔扎哈");        
        String name = list.get(2);//古力娜扎     
        String whoRemoved = list.remove(1);//迪丽热巴
        
        ArrayList<Integer> listC = new ArrayList<>();
       //ArrayList<int> listB = new ArrayList<>();错误,只能写引用类型

⑤List接口实现类LinkedList-多线程

public class LinkedList< E >  implements List< E >

分析

  • LinkedList底层是由链表实现,所以适合添加、删除,不适合查询。因而LinkedList包含大量的操作头尾的方法!

        注意:LinkedList集合特有的方法!!!【多态无法使用子类特有的方法】

        - public void addFirst(E e):将指定元素插入此列表的开头。
        - public void addLast(E e):将指定元素添加到此列表的结尾。
        - public void push(E e):将元素推入此列表所表示的堆栈。

        - public E getFirst():返回此列表的第一个元素。
        - public E getLast():返回此列表的最后一个元素。

        - public E removeFirst():移除并返回此列表的第一个元素。
        - public E removeLast():移除并返回此列表的最后一个元素。
        - public E pop():从此列表所表示的堆栈处弹出一个元素。

        - public boolean isEmpty():如果列表不包含元素,则返回true。

		  LinkedList<String> linked = new LinkedList<>();
		  linked.add("a");

⑥List接口实现类Vector-单线程

		public class Vector< E >  implements List< E >

1.2 Set接口

①Set接口特点

  1. 不允许重复
  2. 无索引

②HashSet集合特点和哈希值

		public class HashSet< E > implements Set< E >
  1. 无序,存取不一致
  2. 底层是哈希表结构查询非常快

哈希值

  • 一个十进制的整数,由系统随机给出的对象地址值,它是一个逻辑地址,模拟的地址,而不是真的物理地址
	
		**哈希值的获取方法:
    	1.直接打印p       16进制
    	2.打印p.toString  16进制
    	3. Object类的方法——int hashCode() 返回对象的哈希值 10进制
	
	 	public native int hashCode();
        	native:代表该方法调用的是本地操作系统的方法
    
    	public String toString() {
        	return getClass().getName() + "@" + Integer.toHexString(hashCode());
    	}		

Person类演示哈希值:

       //如果重写hashCode(),对象地址就会返回1了
  		public class Person extends  Object{
            @Override
            public int hashCode() {  return  1;  }
        }
       
        Person p1 = new Person();
        int h1 = p1.hashCode(); //Person天然继承Object
        System.out.println(p1);//com.itheima.demo03.hashCode.Person@7ef20235
        System.out.println(p1.toString());//com.itheima.demo03.hashCode.Person@7ef20235
        System.out.println(h1);//2129789493  | 1

        Person p2 = new Person();
        int h2 = p2.hashCode();
        System.out.println(p2);//com.itheima.demo03.hashCode.Person@27d6c5e0
        System.out.println(p2.toString());//com.itheima.demo03.hashCode.Person@27d6c5e0
        System.out.println(h2);//668386784   |  1
		
		
        System.out.println(p1==p2);
        //重写hashCode(),即使地址都是1,但真正的物理地址不同,也返回false

String类演示哈希值:

       
        //String类的哈希值——String类重写了Obejct类的hashCode方法
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1.hashCode());//96354
        System.out.println(s2.hashCode());//96354

        System.out.println("重地".hashCode());//1179395
        System.out.println("通话".hashCode());//1179395
    }
}

③HashSet存储数据类型 Integer+Person

Integer

    	Set<Integer> set = new HashSet<>();
    	Collections.addAll(set,3,2,1);
    
    	for (Integer i : set) 
        	System.out.println(i);
	
    	Iterator<Integer> it = set.iterator();
    	while (it.hasNext())
        	Integer n = it.next();
        	System.out.println(n);//1,2,3存取不一致

Person:需重写对象的hashCode和equals,保证HashSet集合唯一性

    	**要求:同名同年龄的人,视为同一个人,只能存储一次
       
        HashSet<Person> set = new HashSet<>();
        Person p1 = new Person("小美女",18);
        Person p2 = new Person("小美女",18);
        Person p3 = new Person("小美女",19);
        System.out.println(p1.hashCode());//1967205423 | 734175839
        System.out.println(p2.hashCode());//42121758 | 734175839

        System.out.println(p1==p2);//false  | 比较的地址依然是 false
        System.out.println(p1.equals(p2));//false | true
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);
        //重写前:p1 p2 p3均会输出,p1 p2哈希值不同 equals也不同,视为2个对象
        //重写后:p2不会输出,p1 p2哈希值同 equals同,视为1个对象

hashCode存储自定义元素必须重写的2个方法!!!

    public class Person {
    	...
  	
    @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); }
      
}
   

④LinkedHashSet集合特点

public class LinkedHashSet< E > extends HashSet< E > implements Set< E >
  • 底层是由一个哈希表(数组+链表/红黑树)+链表实现:多的链表用于维护顺序
        HashSet<String> set = new HashSet<>();
        Collections.addAll(set,"www","abc","abc","itcast");
        System.out.println(set);//[abc, www, itcast] 无序,不允许重复

        LinkedHashSet<String> linked = new LinkedHashSet<>();
        Collections.addAll(linked,"www","abc","abc","itcast");
        System.out.println(linked);//[www, abc, itcast] 有序,不允许重复

⑤Set集合元素不允许的原因

  • 存储时会调用hashCode和equals方法,判断哈希值和内容是否相同
    在这里插入图片描述

2.Map接口

①Map接口的特点

1.双列集合

2.key不可重复 value可重复

②Map接口常用方法

		1.public V put(K key, V value): 
		  return:V  key不重复,返回null
                    key重复,返回被替换的value  
                    
        2.public V remove(Object key): 
          return:V  key不存在,返回null
                    key存在,返回被删除的value               
     
        3.public V get(Object key) 
          return: 
                    key不存在,返回null
                    key存在,返回对应的value值               
    
        4.boolean containsKey(Object key) 

        Map<String,String> map = new HashMap<>();
        map.put("李晨", "范冰冰1");//v1:null      
        map.put("李晨", "范冰冰2");//v2:范冰冰1        
        //此时集合中{李晨=范冰冰2}
        map.put("冷锋","龙小云");
        map.put("杨过","小龙女");
        map.put("尹志平","小龙女");
        //此时集合中{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}

        String v1 = map.remove("李晨");//v1:范冰冰2            
        String v2 = map.remove("林俊杰");//v2:null
   
        String v3 = map.get("杨过");//v3:小龙女
        String v4 = map.get("迪丽热巴");//v4:null   

        boolean b1 = map.containsKey("杨过");//b1:true
        boolean b2 = map.containsKey("赵颖");//b2:false

注意

int V = map.remove("1");
  • 自动拆箱,返回的Value赋值给V ,v是数字的时候可以,v是null则报NullPointerException

③Map接口遍历方法—键找值

键找值:需要借助2个Map接口中的方法

		public Set< K > keySet() //返回map中所有的key到一个set集合中
		public V get(Object key) //返回对应的value

在这里插入图片描述

        //创建Map集合对象,准备使用map中的方法
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        //1.使用keySet(),提取所有的key,一下子存到set集合中 
        Set<String> set = map.keySet();
        
        //2.遍历set集合,一步步得到其中所有key
        for(String key : set){ //set也可以直接写成 map.keySet()
            //3.使用get(key),找到value    
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }

		//2.遍历set集合,一步步得到其中所有key
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //3.使用get(key),找到value    
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
        
      	林志玲=178
		赵丽颖=168
		杨颖=165

④Map接口遍历方法—Entry

Entry:需要借助2个Map接口中的方法

  public Set<Map.Entry<K,V>> entrySet() 
  //Map声明的一个内部接口,返回map中所有的键值对对象到一个set集合中
  
  public interface Map<K, V>{ 
        interface Entry<K, V> {  //Entry将键值对的对应关系封装成了对象
            K getKey();//获取Entry对象中的键。
            V getValue();//获取Entry对象中的值。
            }
  }

在这里插入图片描述

        //创建Map集合对象,准备使用map中的方法
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);


        // 1.使用entrySet(),提取所有的Entry对象,一下子存到set集合中
        Set<Map.Entry<String, Integer>> set = map.entrySet();

        // 2.遍历set集合,一步步得到其中所有Entry对象
        Iterator<Map.Entry<String, Integer>> it = set.iterator();
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();
            
            //3.使用Entry对象中的方法getKey()和getValue()获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            
            System.out.println(key+"="+value);
        }
       
        for(Map.Entry<String,Integer> entry:set){
            //3.使用Entry对象中的方法getKey()和getValue()获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
        
		林志玲=178
		赵丽颖=168
		杨颖=165

2.1 HashMap

①HashMap集合特点

public class HashMap<K,V> implements Map<K,V> 
  • HashMap底层由哈希表实现:数组+单向链表或红黑树(链表的长度超过8): (哈希表结构查询都非常快)
  • hashMap无序集合 多线程
 public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>

②HashMap存储自定义键值类型

<String,Person>分析

  • key:String类型,系统重写String类hashCode方法和equals方法,保证了key唯一性
  • value:Person类型 value可以重复

        HashMap<String,Person> map = new HashMap<>();
        map.put("北京",new Person("张三",18));
        map.put("上海",new Person("李四",19));
        map.put("广州",new Person("王五",20));
        map.put("北京",new Person("赵六",18));
        //字符串重写了hashCode和equals方法,所以张三key北京重复被替换了
              
        Set<String> set = map.keySet();
        for (String key : set) {
            Person value = map.get(key);
            System.out.println(key+"-->"+value);
        }
        
    	上海-->Person{name='李四', age=19}
		广州-->Person{name='王五', age=20}
		北京-->Person{name='赵六', age=18}   
		 

<Person,String>分析

  • key:Person类型,Person类必须重写hashCode方法和equals方法,来保证key唯一性
  • value:String类型 value可以重复
        HashMap<Person,String> map = new HashMap<>();
        map.put(new Person("女王",18),"英国");
        map.put(new Person("秦始皇",18),"秦国");
        map.put(new Person("普京",30),"俄罗斯");
        map.put(new Person("女王",18),"毛里求斯");
        
        Set<Map.Entry<Person, String>> set = map.entrySet();
        for (Map.Entry<Person, String> entry : set) {
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"-->"+value);
        }

	 public class Person {
		 @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);
    	}
 	}

		Person{name='女王', age=18}-->毛里求斯
		Person{name='秦始皇', age=18}-->秦国
		Person{name='普京', age=30}-->俄罗斯
		

③LinkedHashMap集合特点

  • 哈希表+链表 有序
		public class LinkedHashMap<K,V> extends HashMap<K,V>

		HashMap<String,String> map = new HashMap<>();
        map.put("a","a");
        map.put("c","c");
        map.put("b","b");
        map.put("a","d");
        System.out.println(map);// key不允许重复,无序 {a=d, b=b, c=c}

        LinkedHashMap<String,String> linked = new LinkedHashMap<>();
        linked.put("a","a");
        linked.put("c","c");
        linked.put("b","b");
        linked.put("a","d");
        System.out.println(linked);// key不允许重复,有序 {a=d, c=c, b=b}
        

④Hashtable与HashMap

		public class Hashtable<K,V> implements Map<K,V>
		
		HashMap<String,String> map = new HashMap<>();
        map.put(null,"a");
        map.put("b",null);
        map.put(null,null);
        System.out.println(map);//{null=null, b=null}

		//Hashtable不能和null扯上关系
        Hashtable<String,String> table = new Hashtable<>();
        table.put(null,"a");//NullPointerException
        table.put("b",null);//NullPointerException
        table.put(null,null);//NullPointerException

⑤Hashtable子类Properties

  • 参见IO流

⑥of方法一次性添加

三者都是实现了of

  • static < E > List< E > of( ){E… elements}
  • static < E > Set< E > of(){E… elements}
  • static <K, V> Map<K, V> of( ){E… elements}
 		
 		List<String> list = List.of("a", "b", "a", "c", "d");
        System.out.println(list);//[a, b, a, c, d]
        1.'of返回一个不能变的集合,集合不能再使用add,put方法添加元素,会抛出异常'
        list.add("w");//UnsupportedOperationException:不支持操作异常
		
		2.'Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常'
        Set<String> set = Set.of("a", "b", "a", "c", "d");//IllegalArgumentException:非法参数异常,有重复的元素
        Set<String> set = Set.of("a", "b", "c", "d");
        System.out.println(set);
		
		3.'of仅适用于List Set Map 本身,不适用于接口的实现类'
		ArrayList<String> list1 = ArrayList.of("a", "b", "a", "c", "d");  
		    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值