Java基础---集合的概述---list、set、map、泛型、collections

集合的概述

单列集合的体系:
Collection 单列集合的顶层接口
List Collection的子接口,增加了一些特有的方法,有序 可以重复 有索引
ArrayList 底层采用的数组结构实现,顺序存储,查询修改快
LinkedList 底层采用的是双向链表实现,链式存储,增加删除快
Set Collection的子接口,无序 不可以重复 没有索引
HashSet 哈希表存储(数组+单向链表)
LinkedHashSet 可以维护集合元素的顺序
双列集合的体系
Map 双列集合的顶层接口
HashMap 采用的是哈希表进行数据存储
LinkedHashMap 可以维护Map集合中键的顺序

Collection概述

1、单列集合的顶层接口,定义了所有单列集合共有的方法(功能)
2、Collection是一个接口,不能直接创建对象的,找一个实现类去

常用的方法

1、add(Object obj),将obj这个元素添加到集合中
2、remove(Object o)将o这个元素从集合中移除
3、isEmpty();判断集合是否为空
4、size()方法 ,获取集合中元素的个数
5、clear();将集合中的元素清空
6、contains(Object obj); 判断集合中是否包含obj元素

拓展:
数组中使用length,length属性
字符串中 length() 方法
集合中,size()方法 ,获取集合中元素的个数

Collection中带all的方法:toArray()

1、addAll(Collection c)将参数中的c集合中所有的元素,添加到调用者集合中
2、containsAll(Collection c) 如果调用者集合中包含参数集合中所有的元素,返回true否则返回false
3、retainAll(Collection c) 保留调用者集合和参数集合中共有的元素
4、removeAll(Collection c) 移除调用者集合中和参数集合中相同的元素

集合遍历的第一种方式

将集合转成数组,通过遍历数组的方式,间接的遍历集合
Object[] toArray() 将调用者集合装成object类型的数组

public static void main(String[] args) {
		Collection coll = new ArrayList();
		coll.add(520);
		coll.add(true);
		coll.add("大熊猫");
		coll.add('a');
		coll.add(12.23);
		coll.add(new Person("魏无羡", 34));
		System.out.println(coll);
//		将集合转成数组
		Object[] objs = coll.toArray();
		for (int i = 0; i < objs.length; i++) {
			System.out.println(objs[i]);
		}
	}

集合遍历的第二种方法:迭代器

itertor()方法返回的是一个Itertor接口的实现类对象
hasNext();判断集合中是否还有下一个元素
next();获取集合中的下一个元素
remove():删除迭代器正在迭代的对象

public static void main(String[] args) {	
       Collection coll = new ArrayList();
		coll.add(new Person("肖战", 23));
		coll.add(new Person("蔡徐坤", 20));
		coll.add(new Person("卢本伟", 24));
		coll.add(new Person("PDD", 30));
		coll.add(new Person("大司马", 32));

//		通过调用itertor方法,获取该集合的迭代器对象
		Iterator it = coll.iterator();
//		hasNext()
		while (it.hasNext()) {
//		不要使用hasNext()判断一次,就调用多次next方法
			Object next = it.next();
			Person p = (Person) next;
			System.out.println(p.getName() + ":::" + p.getAge());
		}

拓展:集合遍历的第三种方法:foreach

增强for(foreach)
格式:
for(元素的数据类型 元素名称 :要遍历集合){

	}

注意事项:
使用增强for,拿不到元素的索引,无法修改集合或者数组中的元素值
底层是迭代器,所以在遍历的时候,使用集合对象增加或者删除元素的时候,会发生并发修改异常

public static void main(String[] args) {
 // 创建一个集合
     Collection coll = new ArrayList();
     // 在集合中存储元素
     coll.add("a");
     coll.add("b");
     coll.add("d");

     for (Object object : coll) {
        System.out.println(object);
     }
 }

List集合(Collection子接口)

特点:
元素可以重复
可以索引
有序
方法:
从Collection根接口中继承下来的方法(上述常用方法和带all的方法)
在继承的基础上有一些关于下标(索引)的特有的方法:
1、get(int index)获取arraylist中指定索引的元素
2、set(int index,Object obj),修改arraylist中索引为index的元素为obj
3、remove(int index)移除arraylist中指定索引的元素,移除int类型的时候要注意
4、add(int index,Object obj)在索引为index的位置添加元素

List集合的实现类—ArrayList

ArrayList集合是List接口中比较重要的一个实现类
底层实现是:数组
特点: 查询快 增删慢

	public static void main(String[] args) {
		ArrayList arrlist = new ArrayList();
		arrlist.add(234);
		arrlist.add(123);
		arrlist.add(0,"任正非");
		arrlist.add(0,"马化腾");
		System.out.println(arrlist);
//		get(int index)获取arraylist中指定索引的元素
		System.out.println(arrlist.get(1));
//		set(int index,Object obj)
		arrlist.set(3, "马云");
		System.out.println(arrlist);
//		remove(int index)
//      注意:集合中的元素存储的是 Integer 类型的元素时,remove方法中的参数 默认是下标,当明确参数类型是integer的时候 调用的 remove(Object obj).
        arrlist.remove(new Integer(234));
		arrlist.remove(0);
		System.out.println(arrlist);
//      迭代器遍历		
		Iterator it = arrlist.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}

List集合的实现类—LinkedList

LinkedList:也是List集合的实现类
底层实现方式:采用双向链表实现
每一个元素都存储在一个节点中,节点除了元素本身以外,还需要存储下一个元素的内存地址
特点:查询修改慢 增加和删除快

LinkedList中特有的方法:
addFirst()在头部添加元素
addLast()在尾部添加元素
removeFirst()移除头部元素
removeLast()移除尾部元素
getFirst()获取第一个元素
getLast()获取最后一个元素

List集合特有遍历方式

可以通过集合中size()方法和索引进行结合,使用get(index)方法完成对List集合的遍历

package com.DaYu;

import java.util.ArrayList;
import java.util.List;

public class Demo03 {
	public static void main(String[] args) {	
	       List list = new ArrayList();
	       list.add("肖战");
	       list.add("蔡徐坤");
	       list.add("卢本伟");
	       list.add("PDD");
	       list.add("大司马");
	    
	    System.out.println(list);
			for(int i = 0;i<list.size();i++) {
				System.out.println(list.get(i));
			}
	}
}

并发修改异常

1、ConcurrentModificationException
并发修改异常
2、原因
迭代器对象在遍历集合的时候,使用集合对象进行增加和删除的操作(修改不会造成异常)
3、避免方式:两种避免的方式都是针对List集合
方式1:迭代器遍历,迭代器增加和删除
方式2:集合遍历,集合增加和删除
4、列表迭代器:ListIterator,是Iterator 下面的一个子接口,拥有Iterator中的方法,还有特有的方法,可以实 现迭代器遍历迭代器添加。获取ListIterator对象的方式是通过List集合调用listIterator()方法
集合遍历,集合添加:list特有的遍历方式,结合size和get方法,集合添加add

package com.DaYu;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class Demo03 {
	public static void main(String[] args) {	
	       List list = new ArrayList();
	       list.add("肖战");
	       list.add("蔡徐坤");
	       list.add("卢本伟");
	       list.add("PDD");
	       list.add("大司马");
	    
	    System.out.println(list);
	    
			for(int i = 0;i<list.size();i++) {
				if(list.get(i).equals("PDD"))
				list.add("DNF");
			}
			System.out.println(list);
			
		   Iterator it = list.iterator();
		   while(it.hasNext()) {
			   Object next = it.next();
			   if(next.equals("PDD")) {
			   it.remove();
			   }
		   }
		   System.out.println(list);
		   
		   ListIterator itt = list.listIterator();
		   while(itt.hasNext()) {
			   Object next = itt.next();
			   if(next.equals("DNF")) {
				   itt.add("djx");
			   }
		   }
		   System.out.println(list);
	}
}

拓展知识(面试题)

Vector ArrayList LinkedList 三者的区别:
集合体系是在jdk1.2 版本中建立起来,在这之前用的是Vector,从1.2开始Vector属于Collection接口的实现类。
Vector:和ArrayList 底层都是数组实现,只不过线程安全的,效率低下。
ArrayList:底层数组实现 但是线程是不安全,效率高。
LinkedList :和ArrayList都是List接口的实现类,但是底层实现是不同的,LinkedList采用的双向链表的结构进行存储元素,也是线程不安全的。

思考:为什么ArrayList查询修改元素的速度快,增加删除元素慢?
每一个元素是挨着存储的存储空间是连续的,通过首地址和下标就能够很快地定位到每个元素,所以查询和修改快,但是想要添加或删除一个元素时,如果在中间或者头部插入,插入点后面的元素都要移动,所以增加和删除就会很慢。

Set集合(Collection子接口)

1、Set是Collection的一个子接口
2、特点:
无序:没有任何的前后之分,所有的元素没有位置的概念,所有的元素都在集合中
没有索引:集合中没有任何的位置,元素没有位置的属性
不能重复:没有位置的区分,同样的元素没有任何区别,所以不能重复
3、实现类:
HashSet:使用哈希表的存储方法区存储元素

Set集合的遍历

1、没有自己特有的遍历方式,只能使用Collection接口中定义的方法,只能使用Collection中的遍历方式
2、第一种:转成数组,toArray();不带泛型,遍历数组
第二种:转成数组,toArray(T[] arr)带着泛型的数组,得到的是T类型的数组
(1)自己创建的数组大小,小于集合中元素的个数
在调用toArray(T[] arr) 的时候,会返回一个新的数组,并将集合中的元素填充到新数组中
(2)自己创建的数组大小,等于集合中元素的个数
在调用toArray(T[] arr) 的时候,就不会创建新的数组,直接就将集合中的元素填充到数组中,并返回
(3)自己创建的数组大小,大于集合中元素的个数
在调用toArray(T[] arr) 的时候,直接就将集合中的元素填充到数组中,但是对于数组中剩余的位置, 用数组类型的默认值进行填充
3、第三种:迭代器
4、增强for(foreach)

练习

随机生成1020-40之间的随机数,存储在合适的集合中,并进行遍历,随机数不能重复的

package com.DaYu;

import java.util.HashSet;
import java.util.Set;

public class Demo01 {
	public static void main(String[] args) {
		Set<Integer> set = new HashSet<>();
		while(set.size() < 10) {
			int num = (int)(Math.random() * 21 + 20);
			set.add(num);
		}
		for (Integer i : set) {
			System.out.println(i);	
		}
	}
}

HashSet存储自定义类型元素去重原理

1、HashSet是用Hash算法来实现存取对象的,每个对象都有自己的hashCode。
2、当存储自定义类型元素时,在类中必须重写hashCode()和equals()方法。
将hashCode()方法重写为属性相同的对象值返回值必须一样,属性不同的返回值尽量不一样。
将equals()方法重写为属性相同时返回true,属性不同时返回false。
3、在存取对象时,HashSet会调用对象的hashCode来比较集合里面是否有哈希值一样的对象,如果没有,就直接存入,如果有,就调用equals来继续比较hashcode一样的对象,如果返回值为true就不存入,如果返回值为false就存入。

LinkedHashSet

1、是HashSet的一个子类,和HashSet保证元素唯一性的原理相同
2、将每个元素在存储的时候,记录了前后元素的地址
3、效果
可以根据存储元素的顺序,将元素取出
4、使用:
既要保证元素的唯一,又要保证原来的顺序,就可以使用LinkedHashSet

package com.DaYu;

import java.util.LinkedHashSet;
import java.util.Scanner;

public class Demo02 {
//	键盘录入一个字符串,输出其中的字符,并且相同的字符只输出一次,要保证原来的顺序
	public static void main(String[] args) {
//		创建一个LinkedHashSet用来存储字符
		LinkedHashSet<Character> lsh = new LinkedHashSet<Character>();
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个字符串");
		String str = sc.nextLine();
//		将字符串转成字符数组
		char[] chs = str.toCharArray();
		for (char c : chs) {
			lsh.add(c);
		}
		System.out.println(lsh);
//		创建一个StringBuilder对象用来拼接字符
		StringBuilder sb = new StringBuilder();
//		遍历linkedHashSet集合
		for (char c : lsh) {
			sb.append(c);
		}
		System.out.println(sb);
	}
}

List和Set分别有哪些实现类?各个实现类有什么特点

List的实现类包括:ArrayList,LinkedList。
ArrayList和LinkedList的共有特性包括存取是有序的,元素是可重复的,元素是有序列的。
ArrayList的查询速度快,但是增删速度比较慢,
LinkedList的查询速度慢,但是增删速度比较快。

Set的实现类包括:HashSet和LinkedHashSet。
Set的实现类的共有特点包括存取无序,元素不可重复,元素无序列。
HashSet和LinkedHashSet都是用hash算法来存取集合的对象的,LinkedHashSet和HashSet不一样的区别是LinkedHashSet实际上是存取是有顺序的,是无序set中的有序set。

泛型

1、泛型的概述和使用
泛型:广泛的类型,在定义一个类的时候,类型中有些方法参数,返回值类型不确定,就使用一个符号,来表示那么尚未确定的类型,这个符号称为泛型
2、注意事项
1、前后一致:在创建对象的时候,赋值符号前面和后面的泛型要保持一致
2、泛型推断:jdk1.7之后如果前面所属的泛型已经确定了,后面的泛型可以不写(尖括号中可以什么都不写),只写一个<>就可以了
3、不能定义泛型数组,因为如果可以定义泛型数组就会发生泛型擦除,失去了泛型的作用,也就失去了泛型存在的意义

// 有泛型的情况
		List<String> list = new ArrayList<>();
		// list.add(123);//不属于String类型,不能添加进去
		list.add("asdfff");
		list.add("assdf");
		list.add("asdsf");
		System.out.println(list);
		Iterator<String> it = list.iterator();
		while (it.hasNext()) {
			String next = it.next();
			System.out.println(next);
		}

// 没有泛型的情况
		List list = new ArrayList();
		list.add(123);
		list.add(456);
		list.add("java");

		Iterator it = list.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}

Map概述

1、概述
Map双列集合的顶层接口
2、特点
key(键)是唯一的,value(值)不唯一的
每个键都对应唯一的值
3、Map和Collection的区别
Map就是双列集合,是以键值对的形式存放数据,Collection是单列集合,存放就是单个元素
Map中的键是唯一的,Collection中set集合的元素是唯一的
Map的所有操作针对键有效,Collection中针对的是元素

Map中常用的方法

1、增加键值对的方法:put(K key,V value)
2、 remove(Object key) 根据给定的键,删除对应的键值对
clear();清空集合
3、获取方法
get(Object Key) 根据指定的键,获取该键对应的值
size() 获取map集合中键值对的个数
4、判断方法
containsKey(Object Key) 判断集合中是否存在某个键
containsValue(Object value)判断集合中是否存在某个值
5、修改方法
根据给定的键,修改对应的值:put(K key, V value)
如果集合中存在key这个键,那么使用put方法就是修改对应的值,如果集合中不存在key这个键,使用put方法就是在 集合中添加了一个键值对

HashMap

1、就是Map接口的实现类
2、HashMap存储jdk中提供的元素时,可以直接保证元素的唯一性
3、HashMap存储自定义类型的时候,键无法保证元素的唯一性的,要想保证键的元素的唯一性,必须重写HashCode方法和 equals方法
HashMap键的唯一性和HashSet的元素唯一性,保证的方式一样的
4、HashMap和HashSet的关系
HashSet是由HashMap实现的,HashSet就是HashMap中键的那一列
将HashMap中的值那一列隐藏掉,就变成了HashSet

LinkedHashMap

1、是HashMap的一个子类
2、跟HashMap不同之处在于,具有可预知的迭代顺序,存储的键值对和取出的键值对的顺序能够保持一致

Map集合中遍历的第二种思路

1、获取Map集合中所有的键,放到一个Set集合中,遍历Set集合,得到Map集合中的每一个键
根据键再来获取对应的值
2、获取Map集合中的所有键
Set keySet();
3、遍历set集合两种方式
迭代器
增强for循环,foreach
4、拿到Set集合中的每一个键的时候,根据map中的get方法获取键所对应的值

Map集合中遍历的第二种思路

1、获取的map集合中所有的键值对对象(Entry),到set集合中,拿到的是每个键值对对象(Entry),从这个对象中分别获取键和值(根据键值对对象(Entry)提供的方法)
2、根据map集合获取所有的键值对对象,到一个set集合中
Set<Entry<K,V>> entrySet();
3、遍历set集合,两种遍历方式
迭代器
增强for循环
4、遍历Set集合的时候,每一次拿到的都是一个键值对对象
Entry是Map集合中的一个内部接口访问的方式是Map.Entry
Entry常用的方法
getKey():获取键值对对象的键
getValue();获取键值对对象的value值

package com.DaYu;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

//(1)定义一个学生类Student,包含属性:姓名(String name)、年龄(int age)
//(2)定义Map集合,用Student对象作为key,用字符串(此表示表示学生的住址)作为value
//(3)利用四种方式遍历Map集合中的内容,格式:key::value
public class HomeWork01 {
	public static void main(String[] args) {
		Student s1 = new Student("大毛", 11);
		Student s2 = new Student("二毛", 12);
		Student s3 = new Student("三毛", 13);
		Student s4 = new Student("四毛", 14);
		Map<Student, String> map = new HashMap<>();
		map.put(s1, "江苏");
		map.put(s2, "浙江");
		map.put(s3, "四川");
		map.put(s4, "河南");
		System.out.println(map);
		
		Set<Student> set = map.keySet();
		for (Student student : set) {
			System.out.println(student + "::" + map.get(student));
		}
		
		System.out.println("---------------------------------");
		
		Iterator<Student> it = set.iterator();
		while(it.hasNext()) {
			Student next = it.next();
			System.out.println(next+ "::" + map.get(next));
		}

		System.out.println("---------------------------------");
		
		Set<Entry<Student, String>> set2 = map.entrySet();
		for (Entry<Student, String> entry : set2) {
			System.out.println(entry.getKey()+ "::" + entry.getValue());
		}

		System.out.println("---------------------------------");
		
		Iterator<Entry<Student, String>> it2 = set2.iterator();
		while(it2.hasNext()) {
			Entry<Student, String> next = it2.next();
			System.out.println(next.getKey()+ "::" + next.getValue());
		}
	}		
}

Collections工具类

1、常用的方法
binarySearch(List list, T key);在一个有序的List集合中,通过二分查找,找到key所对应的索引
frequency(Collection c ,Object obj)返回的是obj这个元素在c集合中出现的次数
replaceAll(List list, T oldVal, T newVal) 将list集合中的oldval都替换为newVal
shuffle(List<?> list) 将list集合中的元素进行随机置换
swap(List<?> list, int i, int j) 在指定列表的指定位置处交换元素。
synchronizedxxx方法系列:将一个线程不安全的集合传入方法,返回一个线程安全的集合
unmodifiablexxx方法系列:将一个可修改的集合传入方法,返回一个不可修改只读的集合

Collection和Collections的区别

Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。

猜你喜欢

转载自blog.csdn.net/qq_41401295/article/details/106556019