Collection、List、Set、Map集合及泛型

一、Collection集合

集合 : 集合是java中提供的一种容器,可以用来存储多个数据。

数组和集合都是容器,它们的区别
(1)数组长度是固定的,集合长度是可变的
(2)数组中存储的都是同一类型元素,可以存储基本数据类型值。集合存储的都是对象,而且对象的类型可以不一致,在开发中一般当对象多的时候,使用集合进行存储

集合框架
集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map
Collection:单列集合的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.list和java.util.set,其中list的特点是有序、元素可以重复,set的特点是元素无序、而且不可重复,List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,Set接口的主要实现类有java.util.HashSet和java.util.TreeSet.
结构图
在这里插入图片描述
Collection

	@Test
	public void test1() {
		//创建集合对象 可使用多态
		Collection<String> coll = new ArrayList<String>();
		System.out.println(coll);  //重写了toString()方法
		//添加
		boolean b1 = coll.add("张三");
		coll.add("李四");
		coll.add("");
		coll.add("王宇");
		coll.add("天气");
		//判断集合中是否包含指定对象
		boolean b2 = coll.contains("李四");
		//是否为空
		boolean b3 = coll.isEmpty();
		//大小
		int size = coll.size();
		//把集合中的元素存储到数组中
		Object[] arr = coll.toArray();
		for (Object object : arr) {
			System.out.println(object);
		}
		coll.clear();  //清空集合元素不删除集合
	}

Iterator迭代器
Collection接口和Map接口主要是存储元素,而Iterator主要用于迭代访问(遍历)Collection中的元素,因此Iterator对象也称为迭代器

public Interator iterator();获取集合对应的迭代器,用来遍历集合中的元素

/**
	 * 迭代器的使用步骤:
	 * 	1、使用集合中的方法iterator()获取迭代器实现类对象,使用Iterator接口接收(多态)
	 * 	2、使用iterator接口中的方法hashNext判断还有没有下一个元素
	 * 	3、使用iterator接口中的方法next取出集合中的下一个元素
	 */
	@Test
	public void iterator() {
		Collection<String> coll = new ArrayList<>();
		coll.add("姚明");
		coll.add("杨幂");
		coll.add("要从明");
		Iterator<String> it = coll.iterator();
		boolean b = it.hasNext();//判断集合中还有没有下一个元素
		String s = it.next();  //取出集合中的元素
		while(it.hasNext()) {
			String str = it.next();
			System.out.println(str);
		}
		System.out.println("------------------");
		
		for(Iterator<String> it2=coll.iterator();it2.hasNext();) {
			String str = it2.next();
			System.out.println(str);
		}
	}

迭代器实现原理
在这里插入图片描述
增强for循环(只能进行遍历不能进行增删操作底层使用的就是迭代器)

@Test
	public void foreach() {
		int[] arr = {1,2,3,4,5};
		for(int i : arr) {
			System.out.println(i);
		}
		List<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		for(Integer i : list) {
			System.out.println(i);
		}
	}

二、泛型

1、泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候可以使用泛型
2、泛型可以看成是一个变量来接收数据类型
E e :Element元素
T t :Type类型
在这里插入图片描述
3、使用泛型的好处

	/**
	 * 不使用泛型:弊端不安全、不方便
	 */
	@Test
	public void show() {
		//创建集合对象  不使用泛型   默认就是Object类型
		ArrayList list = new ArrayList();
		list.add("111");
		list.add(1);
		Iterator it = list.iterator();
		while(it.hasNext()) {
			Object object = it.next();
			System.out.println(object);
			
			//想使用String类的特有方法length获取字符串长度 
			String s = (String)object;  //会报错
		}
	}
	
	/**
	 * 使用泛型好处
	 * 	1、避免类型转换异常,存储的是什么类型,取出的就是什么类型
	 * 	2、把运行期异常(代码运行之后抛出的异常)提升到了编译器(写代码的时候会报错)
	 */
	@Test
	public void show2() {
		ArrayList<String> list = new ArrayList<>();
		list.add("1");
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			String s = it.next();
			System.out.println(s.length());
		}
	}

4、自定义泛型类模拟ArrayList集合

public class CollectionTest<E> {	
	private E name;
	public E getName() {
		return name;
	}
	public void setName(E string) {
		this.name = string;
	}
}
	@Test
	public void GenericClass() {
		CollectionTest<Integer> gc = new CollectionTest<>();
		gc.setName(21);
		Integer name = gc.getName();
		
		CollectionTest<String> gc2 = new CollectionTest<>();
		gc2.setName("234");
		String strName = gc2.getName();
	}

5、含有泛型的方法和接口

	@Test
	public <E> void methodGenericClass() {
		System.out.println("含有泛型的方法");
	}
	/**
	 * 含有泛型的静态方法
	 */
	@Test
	public static <E> void methodStaticGenericClass() {
		System.out.println("含有泛型的静态方法");
	}
/**
 * 指定接口泛型
 *
 * @param <I>
 */
public interface GenericInterface<I> {

}

6、泛型通配符(注意泛型没有继承概念)

@Test
	public static void test(ArrayList<?> list) {
		Iterator<?> it = list.iterator();
		while(it.hasNext()) {
			Object obj = it.next();
			System.out.println(obj);
		}
	}

7、受限泛型(泛型上限与泛型下限)

	/**
	 * 泛型上限 : ? extends E  代表使用的泛型只能是E的子类或本身
	 * 泛型下限 : ? super E		代表使用的泛型只能是E的父类或本身
	 */
	Collection<Number> coll = null;
	public static void getextends(Collection<? extends Number> coll);
	
	public static void getextends(Collection<? super Number> coll);

三、List集合

1、List接口特点
java.util.list接口extends Collection接口
有序集合,存储元素和取出元素的顺序是一致的(存储123取出123)
有索引,包含了一些带索引的方法
允许存储重复元素
2、List集合常用方法
防止:集合索引越界(数组索引越界,字符串索引越界)

package com.huke.test;

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

public class ListTest {	
	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("a");
		System.out.println(list); //【a,b,c,a】  不是地址重写了toString()方法
		
		list.add(3,"hu");
		System.out.println(list); //【a,b,c,hu,a】
		
		String remove = list.remove(2); //移除c 返回被移除的元素
		
		//用指定元素替换集合中指定位置元素的位置
		String setE = list.set(3, "A");
		
		for(int i = 0;i < list.size();i++) {
			System.out.println(list.get(i));
		}
		
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		
		for (String string : list) {
			System.out.println(string);
		}
	}
}

3、ArrayList集合特点
(1)数组长度不可以改变,ArrayList集合长度可以改变
(2)对于ArrayList集合来说,直接打印得到的不是地址,而是内容,如果内容为空,得到的是空的中括号【】
(3)ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,
(4) ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
(5)ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。

4、ArrayList集合常用方法

package com.huke.test;

import java.util.ArrayList;

public class ArrayListTest {
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<>();
		System.out.println(list); //[]
		//添加方法返回boolean类型
		boolean succese = list.add("张三");
		//返回指定索引数据
		String name = list.get(0);
		//返回被删除元素
		String whoRemove  = list.remove(0);
		//集合长度
		int size = list.size();
		
	}
}

5、ArrayList集合存储的基本数据
如果希望向集合ArrayList当中存储基本数据类型,必须使用基本类型的包装类
基本类型 ------------------------------- 包装类(引用类型,包装类位于java.lang包下)
byte------------------------Byte
short-------------------------Short
int-------------------------------Integer
long---------------------------Long
float----------------------------Float
double----------------------Double
char---------------------------Character
boolean-----------------------------Boolean
6、ArrayList底层实现
(1)首先有三种方式来初始化:

	public ArrayList();
	默认的构造器,将会以默认的大小来初始化内部的数组
	public ArrayList(Collection<? extends E> c)
	用一个ICollection对象来构造,并将该集合的元素添加到ArrayList
	public ArrayList(int initialCapacity) 

(2)ArrayList底层是数组,复制一个数组来扩容

(3)扩容的方法就是 add(E e)
在这里插入图片描述
(4) int newCapacity = oldCapacity + (oldCapacity >> 1);
oldCapacity >> 1 右移运算符 原来长度的一半 再加上原长度也就是每次扩容是原来的1.5倍
之前的所有都是确定新数组的长度,确定之后就是把老数组copy到新数组中,这样数组的扩容就结束了
在这里插入图片描述
(5)无参数构造器代码是初始长度为10
在这里插入图片描述
7、LinkedList集合特点
(1)底层是一个链表结构。查询慢增删快
(2)里边儿包含了大量操作首元素的方法
(3)LinkedList是一个双向链表,如图
在这里插入图片描述
8、LinkedList常用方法

package com.huke.test;

import java.util.LinkedList;

public class LinkedListTest {
	public static void main(String[] args) {
		show01();
		show02();
		show03();
	}

	private static void show03() {
		LinkedList<String> linkedList = new LinkedList<>();
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		System.out.println(linkedList); //[a,b,c]
		if(!linkedList.isEmpty()) {
			//移除第一个元素
			linkedList.removeFirst(); 
			linkedList.poll();
			//移除最后一个元素
			linkedList.removeLast();
		}
		
	}

	private static void show02() {
		LinkedList<String> linkedList = new LinkedList<>();
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		System.out.println(linkedList); //[a,b,c]
		linkedList.clear(); //清空集合中的元素
		if(!linkedList.isEmpty()) {
			linkedList.getFirst();
			linkedList.getLast();
		}
	}

	private static void show01() {
		LinkedList<String> linkedList = new LinkedList<>();
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		System.out.println(linkedList); //[a,b,c]
		//将指定元素添加到头
		linkedList.addFirst("www");
		linkedList.push("www");  //和addFirst()等价
		
		//将指定方法添加到末尾
		linkedList.addLast("com");
	
	}
}

9、Vector集合
Vector集合底层也是数组和ArrayList一样、单线程且同步。

四、Set集合

1、Set接口特点(java.util.Set接口 extends Collection接口)
(1)不允许存储重复元素
(2)没有索引,没有带索引的方法也不能使用普通for循环遍历
2、HashSet集合特点(java.util.HashMap集合 imlements Set接口)
(1)不允许重复元素
(2)没有索引,没有带索引的方法,也不能使用普通的for循环遍历
(3)是一个无序的集合,存储元素和取出元素的顺序有可能不一致
(4)底层是一个hash表(HashMap实例 查询的速度非常快)
3、Set集合遍历(迭代器 增强for)

package com.huke.test;

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

public class SetTest {
  public static void main(String[] args) {
	Set<Integer> set = new HashSet<>();
	set.add(1);
	set.add(1);
	set.add(2);
	set.add(3);
	Iterator<Integer> it = set.iterator();
	while(it.hasNext()) {
		System.out.println(it.next());
	}
	
	for (Integer integer : set) {
		System.out.println(integer);
	}
}
}

4、Set集合不允许存储重复元素原理
set集合存储不重复元素的的前提:必须重写hashCode和equlas放法

在这里插入图片描述
5、HashSet集合存储自定义类型元素
重写HashCode()和Equals()方法

package com.huke.test;

import java.util.HashSet;

/**
 * Set集合不允许存储重复元素
 * 
 * @author 32456
 *
 */
public class SetSaveStringTest {
	public static void main(String[] args) {
		HashSet<Person> set = new HashSet<>();
		Person p1 = new Person("小美女", 18);
		Person p2 = new Person("小美女", 18);
		Person p3 = new Person("小美女", 19);
		set.add(p1);
		set.add(p2);
		set.add(p3);
		System.out.println(p1.hashCode());
		System.out.println(p2.hashCode());
	}
}

class Person {
	private String name;
	private int age;

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	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;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

}

6、LinkedHashSet集合特点(LinkedHashSet extends HashSet)
(1)底层是一个哈希表(数组+链表/红黑树)+链表;多了一条链表(记录元素的顺序),保证元素有序

package com.huke.test;

import java.util.HashSet;
import java.util.LinkedHashSet;

public class LinkedHashSetTest {
     public static void main(String[] args) {
		HashSet<String> set = new HashSet<>();
		set.add("www");
		set.add("www");
		set.add("abc");
		set.add("huke");
		System.out.println(set);
		
		LinkedHashSet<String> linkedHashSetTest = new LinkedHashSet<>();
		linkedHashSetTest.add("www");
		linkedHashSetTest.add("www");
		linkedHashSetTest.add("abc");
		linkedHashSetTest.add("huke");
		System.out.println(linkedHashSetTest);
	}
}

7、可变参数(JDK1.5)
使用前提:当方法的参数列表数据类型已经确定,但是参数个数不确定,就可以使用可变参数
使用格式: 定义方法时使用
修饰符 -------返回值类型--------方法名(数据类型…变量名字){}
可变参数的原理:
可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数,传递的参数个数,可以是0个(不传递),1,2…多个
可变参数有多个必须写在末尾

package com.huke.test;

public class VarArgsTest {
	public static void main(String[] args) {
		int i = add(10, 20);
		System.out.println(i);// 打印一个数组
	}

	// 定义计算(0-n)整数的方法 数据类型已经确定 参数个数不确定
	public static int add(int... arr) {
		System.out.println(arr);
		System.out.println(arr.length);
		int sum = 0;
		for (int i : arr) {
			sum += i;
		}
		return sum;
	}

	public static Object method(Object... objects) {
		for (Object object : objects) {
			System.out.println(object);
		}
		return objects;
	}
}

五、Collections

1、comparable接口实现compareTo()方法

package com.huke.test;

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

public class CollectionsTest {
  public static void main(String[] args) {
	 List<String> list = new ArrayList<String>();
	 //往集合中添加多个元素
	 Collections.addAll(list, "q","2","2","4");
	 //打乱集合元素顺序
	 Collections.shuffle(list);
	 //默认升序排序
	 Collections.sort(list);
	 
	 List<Person2> personList = new ArrayList<>();
	 personList.add(new Person2("张三",18));
	 personList.add(new Person2("王五",17));
	 personList.add(new Person2("人人",15));
	 Collections.sort(personList);
	 
	 
}
  
}
class Person2 implements Comparable<Person2>{
	private String name;
	private int age;
    //Collections方法使用的前提被排序的集合里边儿存储的元素,必须实现Comparable接口
	//重写接口中的方法compareTo()定义排序规则
	
    /**
     * 重写排序规则
     * @param o
     * @return
     */
	@Override
	public int compareTo(Person2 o) {
		//return 0;//认为元素都是相同的
		//自定义比较的规则,比较两个人的年龄(this,参数Person2)
		return this.getAge() - o.getAge();  //年龄升序排序
	}
	
	
	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;
	}

	@Override
	public String toString() {
		return "Person2 [name=" + name + ", age=" + age + "]";
	}

	public Person2() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Person2(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

}

2、Comparator和Comparable的区别
Comparable : 自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则
Compartor :相当于找一个第三方裁判 比较两个

package com.huke.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CollectionsTestSort {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(3);
		list.add(2);
		
		Collections.sort(list, new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 - o2;  //前边儿减去后边默认升序
			}
		});
		List<Person3> person3List = new ArrayList<>();
		Collections.sort(person3List,new Comparator<Person3>() {
			@Override
			public int compare(Person3 o1, Person3 o2) {	
				//按照年龄升序排序
				int result =o1.getAge() - o2.getAge();
				//如果年龄一样 用姓名比较
				if(result == 0) {
					result = o1.getName().charAt(0) - o2.getName().charAt(0);
				}
				return result;
			}
		});
	}
}
class Person3 {
	private String name;
	private int age;
	
	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;
	}

	@Override
	public String toString() {
		return "Person3 [name=" + name + ", age=" + age + "]";
	}

	public Person3() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Person3(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

}

六、Map集合

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

LinkedHashMap<K,V> 集合继承 HashMap<K,V>集合
(1)LinkedHashMap集合底层是哈希表+链表(保证迭代顺序)
(2)LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的

3、Map接口中的常用方法

package com.huke.collection;

import java.util.HashMap;
import java.util.Map;

public class MapTest {
    public static void main(String[] args) {
		show01();
		show02();
		show03();
		show04();
	}
    
    private static void show04() {
    	Map<String,Integer>  map = new HashMap<>();
		map.put("赵丽颖", 168);
		map.put("是多少" , 165);
		map.put("令制冷", 178);
		boolean b1 = map.containsKey("赵丽颖");
		
	}

	private static void show03() {
    	Map<String,Integer>  map = new HashMap<>();
		map.put("赵丽颖", 168);
		map.put("是多少" , 165);
		map.put("令制冷", 178);
		
		Integer v1 = map.get("赵丽颖"); //返回对应值
		Integer v2 = map.get("赵丽颖2");  //返回null
		
	}

	/**
     * key存在 返回被删除的值
     * key不存在 v返回null
     */
    private static void show02() {
		Map<String,Integer>  map = new HashMap<>();
		map.put("赵丽颖", 168);
		map.put("是多少" , 165);
		map.put("令制冷", 178);
		
		int v2 = map.remove("赵丽颖");  //制动拆箱 会报错 null不能赋值给int却可以赋值给Integer 
		Integer v3 = map.remove("赵丽颖");
    }

	/**
     * 存储键值对 key重复时 :会使用新的的value值替换重复的value
     *  存储键值对 key不重复时,返回value
     */
	private static void show01() {
		//创建Map集合 多态
		Map<String,String> map = new HashMap<>();
		String v1 = map.put("李晨", "范冰冰1");
		System.out.println(v1);
		String v2 = map.put("李晨", "范冰冰2");
		System.out.println(v2);
		
		map.put("冷风","龙小云");
		map.put("liukaiwei","养猫");
		map.put("杨幂","刘恺威");
		
	}
}

4、Map集合遍历键找值方式(keySet())
(1)使用Map集合中的方法keySet(),把集合中所有的key取出来,存储到一个set集合中
(2)遍历set集合,获取Map集合中的每一个key
(3)通过Map集合中的方法get(key)通过key找到value

package com.huke.collection;

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

public class KeySetTst {
	 public static void main(String[] args) {
		 Map<String,Integer>  map = new HashMap<>();
			map.put("赵丽颖", 168);
			map.put("是多少" , 165);
			map.put("令制冷", 178);
		Set<String> set = map.keySet();	
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String key = it.next();
			Integer value = map.get(key);
			System.out.println(value);
		}
		
		for (String key : map.keySet()) {
			Integer value = map.get(key);
			System.out.println(value);
		}
	}
}

在这里插入图片描述
5、Entry键值对对象遍历(entrySet())
(1)使用Map集合中的方法entrySet(),把Map集合中的多个Entry对象取出来,存储到一个Set集合中
(2)遍历Set集合,获取到每一个Entry对象
(3)使用Entry对象中的方法getKey()和getValue()获取键与值

package com.huke.collection;

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

public class EntrySetTest {
	public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<>();
		map.put("赵丽颖", 168);
		map.put("是多少", 165);
		map.put("令制冷", 178);
		
		Set<Map.Entry<String, Integer>> set = map.entrySet();
		
		Iterator<Map.Entry<String, Integer>> it = set.iterator();
		while(it.hasNext()) {
			Map.Entry<String, Integer> entry = it.next();
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key);
			System.out.println(value);
		}
		for (Map.Entry<String, Integer> entry : set) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key);
			System.out.println(value);
		}
	}
}

在这里插入图片描述
6、使用HashMap存储自定义类型键值
Map集合保证key唯一 :
作为key元素,必须重写hashCode方法和equals方法,以保证key唯一

package com.huke.collection;

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

/**
 * @author 32456
 *
 */
public class HashMapPersonSavePersonTest {
	public static void main(String[] args) {
		show01();
		show02();
	}
    /**
     * 存储自定义类型键值
     * key :Person类
     * value : String
     */
	private static void show02() {
		Map<Person,String> map = new HashMap<>();
		map.put(new Person("女王",18),"英国");
		map.put(new Person("秦始皇",18),"中国");
		map.put(new Person("女王",18),"毛里裘是");
		
		Set<Map.Entry<Person, String>> set = map.entrySet();
		for (Entry<Person, String> entry : set) {
			Person key = entry.getKey();  //必须重写HashCode和equals方法
			String value = entry.getValue();
			System.out.println(key+value);
		}
		
	}

	private static void show01() {
		Map<String, Person> map = new HashMap<String, Person>();
		map.put("北京", new Person("张三",18));
		map.put("北京", new Person("李四",18));
		map.put("北京", new Person("王五",18));
		map.put("北京", new Person("张三",18));
		
		Set<String> set = map.keySet();
		for (String key : set) {
			Person value = map.get(key);
			System.out.println(value);
		}
		
	}
}
	class Person {
		private String name;
		private Integer age;
		
		
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((age == null) ? 0 : age.hashCode());
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Person other = (Person) obj;
			if (age == null) {
				if (other.age != null)
					return false;
			} else if (!age.equals(other.age))
				return false;
			if (name == null) {
				if (other.name != null)
					return false;
			} else if (!name.equals(other.name))
				return false;
			return true;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public Integer getAge() {
			return age;
		}

		public void setAge(Integer age) {
			this.age = age;
		}

		@Override
		public String toString() {
			return "Person [name=" + name + ", age=" + age + "]";
		}

		public Person() {
			super();
			// TODO Auto-generated constructor stub
		}

		public Person(String name, Integer age) {
			super();
			this.name = name;
			this.age = age;
		}

	}
}

7、LinkedHashMap集合
LinkedHashMap extends HashMap<K,V>
底层原理 :
哈希表 + 链表(记录元素的顺序)

package com.huke.collection;

import java.util.HashMap;
import java.util.LinkedHashMap;

public class LinkedHashMapTest {
    public static void main(String[] args) {
		HashMap<String, String> map = new HashMap<>();
		map.put("a", "a");
		map.put("b", "b");
		map.put("c", "c");
		map.put("d", "d");
		System.out.println(map); //key不允许重复无序
		
		LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
		linkedHashMap.put("a", "a");
		linkedHashMap.put("b", "b");
		linkedHashMap.put("c", "c");
		linkedHashMap.put("d", "d");
		System.out.println(linkedHashMap);
	}
}

8、Hashtable集合
Hashtable集合 implements Map<K,V>接口
Hashtable :底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
Hashtable集合不能存储null值,null键
Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
Hashtable的子类集合Properties依然活跃在历史舞台
Properties集合是唯一一个和IO流相结合的集合
HashMap集合(除了Hashtable的所有集合):可以存储null值,null键

package com.huke.collection;

import java.util.HashMap;
import java.util.Hashtable;

public class HashtableTest {
	public static void main(String[] args) {
		HashMap<String, String> map = new HashMap<>();
		map.put(null, "1");
		map.put("1", null);
		map.put(null, null);
		
		Hashtable<String, String> hashtable = new Hashtable<>();
		hashtable.put(null, null); //报错 空指针异常
		
	}
}

9、练习计算一个字符串每个字符出现的个数

package com.huke.collection;

import java.util.HashMap;
import java.util.Scanner;

public class MapTestChongfu {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.nextLine();
		char[] arr = str.toCharArray();
		HashMap<Character, Integer> map = new HashMap<>();
		for (char key : arr) {
			if(map.containsKey(key)) {
				Integer value = map.get(key);
				value ++;
				map.put(key, value);
			}else {
				map.put(key, 1);
			}
		}
		
		for (Character key : map.keySet()) {
			Integer value = map.get(key);
			System.out.println(value);
		}
	}
}

10、JDK9集合中的add()方法都添加了静态方法的优化of()方法


import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

public class MapTestChongfu {
	public static void main(String[] args) {
		List<Integer> list = List.of(1,2,3,4,5);
		Set<Integer> set = Set.of(1,2,3,4);
		HashMap<String,Integer> map = HashMap.of("张三","张三","李四",18);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值