Java集合总结

Java集合及其工具类

一、常用的两种遍历集合的方法
  • 迭代器的实现

      Iterator<String> it =coll.iterator();
      while(it.hasNext()){
      String line =it.next();
      System.out.println(line);
      }
    

    实现原理: 首先指针会指向集合的-1索引,判断hasNext之后就会输出next直到最后一位。

  • 增强for循环
    底层使用的也是迭代器,使用for循环的格式,简化了迭代器的书写
    所有的单列集合都可以使用增强性for循环
    作用: 用来遍历数组或者集合

    格式:
    for(集合/数组的数据类型 变量名:集合/数组名){
    System.out.println(变量名);
    }

二、泛型
  • 泛型: 泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候可以使用泛型,泛型也可以看作一个变量,用来接受数据类型
    E e:Element 元素
    T t: Type 类型
    例:ArrayList源码中,ArrayList不知道将要保存什么数据类型,所以使用泛型E
    表示未知的数据类型
    ##当创建集合对象的时候就会确定泛型的数据类型
    例:List < String > list =new Arraylist<>();
    会把数据类型作为参数传递,把String的值传给E

    List< Student> list =new ArrayList<>();
    此时,会把Student的值作为参数传递给E

  • 使用泛型的好处:
    创建集合对象,不使用泛型
    好处:集合不使用泛型,默认使用Object类型,可以存储任意类型的数据
    弊端:不安全,会引发数据异常:类型转换异常 java.lang.ClassCastException

    创建集合对象,使用泛型
    好处:避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
    把运行期的异常(运行代码时候的异常)提升到了编译期的异常(写代码时期)

  • 定义含有泛型的方法: 泛型定义在修饰符和返回值之间
    格式:

    修饰符 <泛型> 返回值类型 方法名(参数列表(可以使用泛型)){
    方法体;
    }

    含有泛型的方法,在调用方法的时候确定泛型的类型
    传递什么类型的参数,泛型就是什么类型
    public static void method(E e){
    System.out.println(e);
    }
    //这里,如果传递的是一个String类型的数据,则输出的即为字符串类型

  • 泛型的通配符: ?代表任意的数据类型
    使用方式:不能创建对象使用,只能作为方法的参数使用
    例如:创建一个方法,能遍历所有的ArrayList集合
    这是时候我们不知道这是什么数据类型,所以使用泛型的通配符?来接收数据
      注意:泛型是没有继承概念的

      public static void printArray(ArrayList<?> list){
      //使用迭代器遍历集合
      Iterator<?> it=list.iterator();
      while(it.hasNext()){
      it.next()方法取出的是Object类型的数据,可以接受任何数据类型
      Object obj =it.next();
      System.out.println(obj);
      	}
      }
    

    泛型的上限限定和泛型的下限限定
    上限限定:?extends E 代表使用的泛型只能是E类型的本身或子类
    下限限定:?super E 代表使用的泛型只能是E类型的本身或父类

三、List集合
  • List 集合:list接口继承collection接口。
    list接口的特点
      1、有序的集合,存储元素的顺序是一致的
      2、有索引,包含了一些带索引的方法
      3、允许存储重复的元素
    list接口中带索引的方法:
      1、public void add(int index,E element)
      2、public E get(int index)
      3、public E remove(int index)
      4、public E set(int index,E element)

       注意:操作索引的时候,一定要注意防止索引越界
    打印list集合的三种方法:
      普通的for循环   增强型for循环    Iterator

    • ArrayList集合:
      集合数据的存储结构是数组结构,元素的查找快、增删慢,在日常的开发中使用最多的是数据查询,遍历数据

    • LinkedList集合:
      1、底层是一个链表结构:查询慢,增删快
      2、里面包含了大量操作首位元素的方法
      注意:使用LinkedList集合特有的方法,不能使用多态

      插入方法: addFirst() 插入开头
            addLast() 插入结尾
            push() 将元素推入此列表表示的堆栈

      返回: getFirt() 返回列表的第一个元素
         getLast() 返回列表的最后一个元素

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

      判断是否为空: boolean isEmpty()

    • Vector: 底层与数组一样,底层使用索引进行存储。Vector是同步的,代表是单线程,索引存储速度慢

四、Set集合:

特点:1、不允许存储重复的元素
   2、没有索引,没有带索引的方法,也不能使用普通的for循环遍历

  • HashSet集合implements Set接口
      HashSet特点:
      1、不允许存储重复的元素
      2、没有索引,没有带索引的方法,也不能使用普通的for循环遍历
      3、是一个无序的集合,存储元素和取出元素的顺序可能不一致
      4、底层是一个哈希表结构(查询速度非常快)

  • HashSet集合不能使用普通的for循环遍历,可以使用增强型for循环和迭代器

  • 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到    的地址不是数据实际存储的物理地址)
      在Object类中有一个方法,可以获取对象的哈希值
      int hashCode():返回该对象的哈希码值
      hashCode 的源码:
          public native int hashCode();
      代表该方法调用的是本地操作系统的方法
      HashSet集合存储数据的结构(哈希表
      jdk1.8版本之前:哈希表=数组+链表
      jdk1.8/版本之后:哈希表=数组+链表
              哈希表=数组+红黑树(提高查询速度)
      哈希表的特点:速度快
      存储数据到集合中,先计算元素的哈希值,相同哈希值的元素分为一组,链表/红黑树结构把相同哈希  值的元素连接在一起
      如果链表的长度超过了9位,那么就会把链表转换为红黑树(提高查询速度)
      note:两个元素不同,但是哈希值相同,被称为哈希冲突
      Set集合存储元素不重复的原理:Set集合在调用add方法的时候,会调用元素的hasCode方法和    equals方法,判断元素是否重复
      HashSet集合在存储自定义类型的元素的时候,必须要重写HashCode方法和equals方法,这样才     能保证不会存储相同的元素

  • LinkedHashSet:底层是一个哈希表(数组+链表/红黑树)+链表(多了一条链表,记录元素的存储位置,   保证元素的有序)

  • 可变参数:是JDK1.5之后出现的新特性
      使用前提:当方法的参数列表数据类型已经确定,但是参数的个数不确定,此时可以使用可变参数
      使用格式:定义方法的时候使用:
      修饰符 返回值类型 方法名(数据类型…变量名){}
      可变参数的原理:可变参数的底层就是一个数组,根据传入参数个数的不同,创建不同长度的数组
      可变参数的注意事项: 1、一个方法的参数列表,只能有一个可变参数
                 2、如果方法的参数有多个,那么可变参数一定要写在参数列表的末尾

五、Collections集合类:

  • 1、addAll(集合变量名,添加的元素……)
      shuffle(集合变量名)
  List<String> list =new ArrayList<>();  
  //往list集合中添加元素
  Collections.addAll(list, "a","b","c","d","e","f","g","h");
  System.out.println(list);
  
  //把list集合打乱顺序
  Collections.shuffle(list);
  System.out.println(list);	
  • 2、 sort(集合变量名)方法
        public static void main(String[] args) {
	  ArrayList<Integer> list =new ArrayList<>();
  	Collections.addAll(list, 1,2,3,4,5,8,7,6);
  	System.out.println(list);	//[1, 2, 3, 4, 5, 8, 7, 6]
  	Collections.sort(list);
  	System.out.println(list);	//[1, 2, 3, 4, 5, 6, 7, 8]
		
		
		List<Person> p=new ArrayList<>();
		p.add(new Person("张三", 18));
		p.add(new Person("李四", 20));
		p.add(new Person("王五", 15));
		System.out.println(p);	//[Person [name=张三, age=18], Person [name=李四, age=20], Person [name=王五, age=15]]

		//在person这个类中,重写compareto方法,this.getAge()-o.getAge()为升序,反之为降序
		//注意:在类名之后要implements Compareble接口<Person>,因为是将Person作比较,所以要将泛型写成Person
		Collections.sort(p);
		System.out.println(p);	//[Person [name=王五, age=15], Person [name=张三, age=18], Person [name=李四, age=20]]
	}
  • 3、sort(集合变量名,new Comparator< T>(){
    @Override
    public int compare(T t1,T t2){
    return 0;
    //这里用t1-t2代表0,表示升序。使用o2-o1则表示降序
    }
    })

    这个和2中的方法代码区别在参数不同,3中的排序方式可以自己改变(升序、降序)

六、Map集合

* Map集合: java.util.Map<k,v>集合
* Map集合的特点:
1、Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2、Map集合的元素,key和value的数据类型可以相同,也可以不同
3、Map集合中的元素,key是不允许重复的,value是可以重复的
4、Map集合中的元素,key和value的值是一一对应的
java.util.HashMap<k,v>集合 implements Map<k,v>接口
* HashMap集合的特点:
1、HashMap集合的底层是哈希表,查询的速度特别快
JDK1.8之前:数组+单项链表
JDK1.8之后:数组+单项链表/红黑树(链表的长度超过8,就会使用红黑树),提高查询速度
2、HashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
* LinkedHashMap的特点:
1、LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
2、LinkedHashMap集合是一个有序的集合,存取元素的顺序是一致的

  • Map集合的第一种遍历方式:通过键找值的方式
    Map集合中的方法:
    Set keySet返回映射中包含的键的Set视图
    实现步骤:
    1、使用Map集合中的方法KeySet(),把Map集合所有的key取出来,存储到一个Set集合中
    2、遍历Set集合,获取Map集合中的每一个Key
    3、通过Map集合中的方法get(key),通过key找到value

    源代码如图所示:

		public static void Demo02() {
		Map<String,Integer> map=new HashMap<>();
		map.put("张三", 18);
		map.put("李四", 15);
		map.put("王五", 20);
		//使用Map集合的keyset(),把集合当中的所有的key取出来,存储到一个set集合中
		Set<String > set=map.keySet();
	    //使用迭代器遍历set集合的每一个key
	    Iterator<String > it =set.iterator();
	    while(it.hasNext()) {
	    	String key=it.next();
	    	Integer value =map.get(key);
	    	System.out.println(key+"="+value);
	    }
	   // 以下为增强型for循环遍历集合
	    for(String key:map.keySet()) {
	    	Integer value=map.get(key);
	    	System.out.println(key+"="+value);
	    }
	}
  • Map集合遍历的第二种方式:使用Entry对象遍历
    Map集合中的方法:Set<Map.Entry<K,V>> entrySet() 返回映射中包含的映射关系的Set视图
    实现步骤:
    1、使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
    2、遍历Set集合,获取每一个Entry对象
    3、使用Entry对象中的方法getKey()和getValue()获取键与值
	public static void Demo03() {
		Map<String,Integer> map=new HashMap<>();
		map.put("张三", 18);
		map.put("李四", 20);
		map.put("王五", 15);
		//将Map集合中的方法entrySet(),把Map集合中的多个Entry对象取出来,存储到一个set集合当中
		Set<Map.Entry<String, Integer>> set =map.entrySet();
		//迭代器输出
		Iterator<Entry<String, Integer>> it =set.iterator();
		while(it.hasNext()) {
			//使用Entry对象的getKey和getValue获取键与值
			Map.Entry<String, Integer> entry=it.next();
			String key=entry.getKey();
			int value=entry.getValue();
			//使用迭代器遍历map集合中的元素
			System.out.println(key+"="+value);
		}
		System.out.println("============以下为增强型for循环================");
		for(Map.Entry<String, Integer> entry:set) {
			String key=entry.getKey();
			int value=entry.getValue();
			System.out.println(key+"="+value);
		}
	}
  • hashMap集合存储自定义类型的键值:
    Map集合保证key值是唯一的:作为key的元素,必须重写hasCode和equals方法,以保证键值的唯一

    代码如下所示:

		public static void Demo04() {
		Map<String,Person> map=new HashMap<>();
		map.put("北京", new Person("张三", 18));
		map.put("上海", new Person("李四", 15));
		map.put("深圳", new Person("王五", 22));
		map.put("北京", new Person("赵六", 28));
		//使用keyset()拿到key
		Set<String > set=map.keySet();
		//用迭代器遍历集合
		Iterator<String> it=set.iterator();
		while(it.hasNext()) {
			String key=it.next();
			Person value=map.get(key);
			System.out.println(key+"="+value);
		}
	}
		public static void Demo05() {
		Map<Person,String> map=new HashMap<>();
		map.put( new Person("张三", 18), "北京");
		map.put( new Person("李四", 15),"上海");
		map.put( new Person("王五", 22),"深圳");
		map.put( new Person("张三", 18),"北京");
		//用Entry拿到key-value键值对
		Set<Map.Entry<Person, String>> set =map.entrySet();
		//用增强型for循环遍历集合
		for(Map.Entry<Person, String> entry:set) {
			Person key=entry.getKey();
			String value =entry.getValue();
			System.out.println(key+"="+value);
		}
	}
  • LinkedhashMap集合:
    底层是哈希表+链表结构
    note:这层链表结构使集合的存取变得有序

    HashMap:无序且不可重复
    LinkedHashMap:有序且不可重复

  • Hashtable集合:
    java.util.Hashtable<k,v>集合 implements Map<k,v>接口
    Hashtabel:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
    HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快

    HashMap集合(之前学的所有集合):可以存储null值,null键
    Hashtable集合:不能存储null值,null键

    Hashtable和vector集合一样,在jdk1.2版本之后被被先进的集合(HashMap,ArrayList)取代了
    Hashtable 的子类propertices依然活跃在历史舞台
    propertices集合是唯一一个和IO流相结合的集合

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值