java学习13

数据结构

先进后出
【入口和出口在同一侧】

存储元素到集合:入、压栈
取出集合中的元素:出、弹栈

队列

先进先出
【入口和出口在集合的两侧】

数组

查询快,增删慢
【数组的地址是连续的,通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素】
【数组的长度是固定的,想要增加/删除一个元素,必须创建一个新数组,把源数组的数据复制过来】

链表

查询慢,增删快
【链表中地址不是连续的,每次查询元素必须从头查询】
【链表结构增加/删除一个元素,对链表的整体结构没有影响,所以增删快】

链表中的每一个元素也称之为一个节点。
一个节点包含了一个数据源(存储数据),两个指针域(存储地址)。【自己的地址 | 数据 | 下一个节点的地址】

单向链表: 链表中只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序可能不一致)。
双向链表: 链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合。

红黑树

二叉树:分支不能超过两个。

排序树/查找树:在二叉树的基础上,元素是有大小顺序的。(左子树小,右子树大)

平衡树:左孩子和右孩子相等。
不平衡树:左孩子不等于右孩子。

红黑树: 特点趋近于平衡树,查询速度非常快,查询叶子节点最大次数不能超过最小次数的二倍。
【节点可以是红色的或黑色的】
【根节点是黑色的】
【叶子节点(空节点)是黑色的】
【每个红色的节点的子节点都是黑色的】
【任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同】

List集合

java.util.List extends Collection

List接口的特点:
1.有序的集合,存储元素和取出元素的顺序是一致的。
2.有索引,包含一些带索引的方法。
3.允许存储重复的元素。

List接口中带索引的方法(特有):

操作索引时要注意索引越界异常
【IndexOutOfBoundsException】索引越界异常,集合会报
【ArrayIndexOutOfBoundsException】数组越界异常
【StringIndexOutOfBoundsException】字符串越界异常

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)
	【用指定元素替换集合中指定位置的元素,返回更新前的元素】
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Demo01List {
	
	public static void main(String[] args) {
		
		//创建一个List集合对象,使用多态
		List<String> list = new ArrayList<String>();
		//使用add方法添加元素
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		//打印list
		System.out.println(list);//[1, 2, 3, 4]	重写了toString方法
		
		//public void add(int index,E element)
		list.add(2, "a");
		//打印list
		System.out.println(list);//[1, 2, a, 3, 4]
		
		//public E get(int index)
		String s1 = list.get(2);
		System.out.println(s1);//a
		System.out.println(list);//[1, 2, a, 3, 4]
		
		//public E remove(int index)
		String s2 = list.remove(2);
		System.out.println(s2);//a
		System.out.println(list);//[1, 2, 3, 4]
		
		//public E set(int index,E element)
		String s3 = list.set(2, "A");
		System.out.println(s3);//3
		System.out.println(list);//[1, 2, A, 4]
		
		//List 集合有三种遍历方式
		//普通for循环
		for(int i = 0; i < list.size(); i++) {
			String s = list.get(i);
			System.out.print(s);//12A4
		}
		System.out.println();
		//迭代器
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			String s = it.next();
			System.out.print(s);//12A4
		}
		System.out.println();
		//增强for循环
		for(String s : list) {
			System.out.print(s);//12A4
		}
	}

}

ArrayList集合

java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快。

LinkedList集合

java.util.Linked集合 implements List接口

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

1.	public void addFirst(E e)
	【将指定元素插入该列表的开头】

2.	public void addLast(E e)
	【等效于add方法】
	【将指定元素添加到该列表的末尾】

3.	public E getFirst()
	【返回此列表的第一个元素】

4.	public E getLast()
	【返回此列表的最后一个元素】

5.	public E removeFirst()
	【相当于E remove()方法】
	【移除并返回此列表的第一个元素】

6.	public E removeLast()
	【移除并返回此列表的最后一个元素】

7.	public E pop()
	【相当于removeFirst()方法】
	【从此列表所表示的堆栈出弹出一个元素】

8.	public void push(E e)
	【等效于addFirst(E)】
	【将元素推入此列表所表示的堆栈】

9.	public boolean isEmpty()
	【如果列表不包含元素,返回true】	
import java.util.LinkedList;

public class Demo02LinkedList {
	
	public static void main(String[] args) {
//		method1();
//		method2();
		method3();
	}

	private static void method3() {
		//创建LinkedList对象
		LinkedList<String> linked = new LinkedList<>();
		//添加元素
		linked.add("a");
		linked.add("b");
		linked.add("c");
		
		//E removeFirst 等价 E pop 等价 E remove()		E removeLast  
//		String first = linked.removeFirst();
//		String first = linked.remove();
		String first = linked.pop();
		System.out.println(first);//a
		String last = linked.removeLast();
		System.out.println(last);//c
		System.out.println(linked);//[b]
	}

	private static void method2() {
		//创建LinkedList对象
		LinkedList<String> linked = new LinkedList<>();
		//添加元素
		linked.add("a");
		linked.add("b");
		linked.add("c");
		
		//E getFirst		E getLast		boolean isEmpty
		if(! linked.isEmpty()) {
			String first = linked.getFirst();
			System.out.println(first);//a
			String last = linked.getLast();
			System.out.println(last);//c
		}
	}

	private static void method1() {
		//创建LinkedList对象
		LinkedList<String> linked = new LinkedList<String>();
		//添加元素
		linked.add("a");
		linked.add("b");
		linked.add("c");
		
		//void addFirst 等价 void push		void addLast
		linked.addFirst("A");
		System.out.println(linked);//[A, a, b, c]
		
		linked.addLast("C");
		System.out.println(linked);//[A, a, b, c, C]
		
		linked.push("A");
		System.out.println(linked);//[A, A, a, b, c, C]
		
	}

}

Vector集合(了解)

底层是数组,是同步的(单线程)

Set接口

java.util.Set接口 extends Collection接口

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

HashSet集合

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

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

public class Demo03Set {

	public static void main(String[] args) {
		
		//创建一个Set对象
		Set<Integer> set = new HashSet<Integer>();
		//添加元素
		set.add(1);
		set.add(2);
		set.add(1);
		set.add(4);
		
		System.out.println(set);//[1, 2, 4]	重写了toString方法
		
		//遍历set
		//使用迭代器遍历
		Iterator<Integer> it = set.iterator();
		while(it.hasNext()) {
			int i = it.next();
			System.out.print(i);//124
		}
		System.out.println();
		//使用增强for遍历
		for(int i : set) {
			System.out.print(i);//124
		}
		
	}
	
}

HashSet集合存储数据的结构(哈希表)

哈希值: 是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)

在Object类有一个方法,可以获取对象的哈希值

int hashCode()
【返回该对象的哈希码值】
	
	hashCode方法的源码:
		public native int hashCode()
		【native代表该方法调用的是本地操作系统的方法】

哈希表
jdk1.8之前 :
哈希表=数组+链表

jdk1.8之后 :
哈希表=数组+链表
哈希表=数组+红黑树(提高查询的速度)

哈希表的特点:速度快

Set存储元素不重复的原理

前提: 存储的元素必须重写hashCode方法和equals方法

Set集合在调用add方法时,add方法会调用元素的hashCode方法和equals方法,判断元素是否重复。

哈希值相同equals方法返回true时,将元素存入集合。

HashSet存储自定义类型元素
给HashSet中存放自定义类型元素时,需要重写对象中的hashcode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一

/*
 * 同年龄同名视为同一人,只能存储一次
 */

import java.util.HashSet;

public class Demo04HashSetSavePerson {
	
	public static void main(String[] args) {
		
		//创建HashSet集合存储Person对象
		HashSet<Person> set = new HashSet<>();
		Person p1 = new Person("周老大",3);
		Person p2 = new Person("周老二",2);
		Person p3 = new Person("周老二",2);
		
		set.add(p1);
		set.add(p2);
		set.add(p3);
		
		System.out.println(set);//[Person [name=周老大, age=3], Person [name=周老二, age=2]]
		
	}

}
public class Person {
	
	private String name;
	private int age;
	
	public Person() {
		
	}
	
	public Person(String name, int age) {
		this.name = name;
		this.age = 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;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + 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;
	}
	

}

LinkedHashSet集合

java.util.HashSet集合 extends HashSet集合 implements Set集合

特点:
底层是一个哈希表(数组+链表/红红黑树)+链表(记录元素的存储顺序),保证元素有序。

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

public class Demo05LinkedHashSet {
	
	public static void main(String[] args) {
		
		HashSet<String> set = new HashSet<>();
		set.add("a");
		set.add("c");
		set.add("b");
		set.add("a");
		System.out.println(set);//[a, b, c]
		
		LinkedHashSet<String> linked = new LinkedHashSet<>();
		linked.add("a");
		linked.add("c");
		linked.add("b");
		linked.add("a");
		System.out.println(linked);//[a, c, b]
	}

}

可变参数

可变参数是java1.5之后出现的新特性。

使用前提 :
当方法的参数列表的数据类型已经确定,但参数的个数不确定,就可以使用可变参数。

使用格式:
定义方法时使用

修饰符 返回值类型 方法名(数据类型...参数名称){}

可变参数的原理:
可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数。

传递的参数个数可以是任意多个也可以不传递(0个)。

public class Demo01varArgs {
	
	public static void main(String[] args) {
		add();
		
	}
	//add():就会创建一个长度为0的数组。int[] arr = {};	传几个参数创建的数组长度就为几。
	public static int add(int...arr) {
		System.out.println(arr);//[I@60f82f98	底层是一个数组
		System.out.println(arr.length);//0
		return 0;
	}

}

注意:

1.一个方法的参数列表只能有一个可变参数。
2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾。

可变参数的特殊(终极)写法

public static void method(Object...obj){}
public class Demo01varArgs {
	
	public static void main(String[] args) {
		int request = add(1,2,3,10,90);
		System.out.println(request);
	}
	
	public static int add(int...arr) {
		int sum = 0;
		for(int i : arr) {
			sum += i;
		}
		return sum;
	}

}

Collections集合工具类

1.	public static <T> boolean addAll(Collection<T> c,T...elements)
	【往集合中添加一些元素】

2.	public static void shuffle(List<?> list)
	【打乱集合顺序】

3.	public static <T> void sort(List<T> list)
	【将集合中的元素按照默认规则排序(升序)】
	【被排序的集合里面的元素必须实现Comparable,重写里面的CompareTo定义排序规则】
	
4.	public static <T> void sort(List<T> list,Comparator<? super T>)
	【将集合中元素按照指定规则排序】

Comparable和Comparator的区别:
Comparable: 自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则compareTo方法。
Comparator: 相当与找一个第三方裁判来比较。

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

public class Demo07Collections {
	
	public static void main(String[] args) {
		
		ArrayList<Integer> list = new ArrayList<>();
		
		Collections.addAll(list, 1,2,3,4,5);
		System.out.println(list);//[1, 2, 3, 4, 5]
		
		Collections.shuffle(list);
		System.out.println(list);//[4, 1, 3, 2, 5]
		
		Collections.sort(list);
		System.out.println(list);//[1, 2, 3, 4, 5]
		
		ArrayList<People> list1 = new ArrayList<People>();
		list1.add(new People("周老大",3));
		list1.add(new People("周老三",1));
		list1.add(new People("周老二",2));
		Collections.sort(list1);
		System.out.println(list1);
		//[People [name=周老大, age=3], People [name=周老二, age=2], People [name=周老三, age=1]]
	}

}
public class People implements Comparable<People>{
	
	private String name;
	private int age;
	
	public People() {
	}
	
	public People(String name, int age) {
		this.name = name;
		this.age = age;
	}
	

	@Override
	public String toString() {
		return "People [name=" + name + ", age=" + 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 int compareTo(People o) {
		// TODO Auto-generated method stub
//		return 0;//认为元素都是相同的
//		return o.getAge() - this.getAge();//按年龄降序排序
		return this.getAge() - o.getAge();//按年龄升序排序
	}
	

}

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

public class Demo08Sort {

	public static void main(String[] args) {
		ArrayList<Integer> list01 = new ArrayList<>();
		Collections.addAll(list01,1,3,4,2,7,0);
		System.out.println(list01);//[1, 3, 4, 2, 7, 0]
		
		Collections.sort(list01, new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				// TODO Auto-generated method stub
				return o1 -o2;
			}
		});
		System.out.println(list01);//[0, 1, 2, 3, 4, 7]
		
		ArrayList<Student> list02 = new ArrayList<>();
		list02.add(new Student("周老大",3));
		list02.add(new Student("周老三",1));
		list02.add(new Student("b周老二",2));
		list02.add(new Student("a周老二",2));
		System.out.println(list02);
		//[Student [name=周老大, age=3], Student [name=周老三, age=1], Student [name=b周老二, age=2], Student [name=a周老二, age=2]]
		
		Collections.sort(list02, new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				// TODO Auto-generated method stub
//				return o1.getAge()-o2.getAge();//升序
				//如果两个人年龄一样就按姓名的第一个字排序
				int result = o1.getAge() - o2.getAge();
				if(result == 0) {
					result = o1.getName().charAt(0) - o2.getName().charAt(0);
				}
				return result;
			}
		});
		System.out.println(list02);
		//[Student [name=周老三, age=1], Student [name=b周老二, age=2], Student [name=a周老二, age=2], Student [name=周老大, age=3]]
		//[Student [name=周老三, age=1], Student [name=a周老二, age=2], Student [name=b周老二, age=2], Student [name=周老大, age=3]]
	}
	
	
}
public class Student {
	
	private String name;
	private int age;
	
	public Student() {
		
	}
	
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + 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;
	}
	

}

Map集合

java.util.Map<K,V>集合

Map集合的特点:

1.Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2.Map集合中的元素,key和value的数据类型可以相同也可以不同
3.Map集合中的元素,key值是不允许重复的,value是可以重复的
4.Map集合中的元素,key和value是一一对应的
Map集合常用子类

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接口中常用的方法
1.	public V put(K key,V valiue)
	【把指定的键和指定的值添加到对应的Map集合中去】
	【存储键值对的时候,K不重复,返回值是null】
	【存储键值对的时候,K重复,会使用新的value替换Map中重复的value,返回被替换的value】

2.	public V remove(Object key)
	【把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值】
	【key不存在时,返回null】

3.	public V get(Object key)
	【根据指定的键,在Map中获取对应的值】
	【K不存在返回null】

4.	boolean containsKey(Object key)
	【判断集合中是否包含指定的键】
import java.util.HashMap;
import java.util.Map;

public class Demo09Map {
	
	public static void main(String[] args) {
		
		method1();//public V put(K key,V valiue)
		method2();//public V remove(Object key)
		method3();//public V get(Object key)
		method4();//public boolean containsKey(Object key)
		
	}
	private static void method4() {
		//boolean containsKey(Object key)	包含指定的键返回true,不包含返回false
		//创建Map集合对象
		Map<Integer,Double> map = new HashMap<>();
		//向map中存储键值对
		map.put(1,1.1);
		map.put(2,1.2);
		map.put(3,1.3);
		System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
		
		boolean b1 = map.containsKey(2);
		System.out.println(b1);//true
		System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
		
		boolean b2 = map.containsKey(0);
		System.out.println(b2);//false
		
	}
	private static void method3() {
		//public V get(Object key)	K不存在时返回null
		//创建Map集合对象
		Map<Integer,Double> map = new HashMap<>();
		//向map中存储键值对
		map.put(1,1.1);
		map.put(2,1.2);
		map.put(3,1.3);
		System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
		
		Double v1 = map.get(2);
		System.out.println(v1);//1.2
		System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
		
		Double v2 = map.get(0);
		System.out.println(v2);//null
		System.out.println(map);//{1=1.1, 2=1.2, 3=1.3}
		
	}
	private static void method2() {
		//public V remove(Object key) K不存在时返回null,存在则返回被删除value
		//创建Map集合对象
		Map<Integer,Integer> map = new HashMap<>();
		//向map中存储键值对
		map.put(1, 01);
		map.put(2, 02);
		map.put(3, 03);
		System.out.println(map);//{1=1, 2=2, 3=3}
		
		Integer value01 = map.remove(2);
		System.out.println(value01);//2
		System.out.println(map);//{1=1, 3=3}
		
//		int value02 = map.remove(2);//NoPointException 空指针异常
		Integer value02 = map.remove(2);
		System.out.println(value02);//null
		System.out.println(map);//{1=1, 3=3}
	}
	private static void method1() {
		//public V put(K key,V valiue) K值不存在时返回null,存在时返回被替换的value
		//创建Map集合对象
		Map<Integer,String> map = new HashMap<>();
		String value01 = map.put(1,"1");
		System.out.println(value01);//null
		System.out.println(map);//{1=1}
		
		String value02 = map.put(1,"2");
		System.out.println(value02);//1
		System.out.println(map);//{1=2}
	}

}
1.	public Set<K> keySet()
	【获取Map集合中所有的键,存储到Set集合中】
	【通过键找值遍历Map集合】

2.	public Set<Map.Entry<K,V>> entrySet()
	【将Map集合中所有键值对对象(Entry对象)存储到Set集合】
		Entry对象中的方法:
			getKey()【获取key】
			getValue()【获取value】

Map.Entry<K,V>: 在Map接口中有一个内部接口Entry

作用:当Map集合一创建,那么就会在Map集合中创建一个Entry对象,用来记录键与值(键值对对象,键与值的映射关系)

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

/*
 * Map 的第一种遍历方式,通过键找值
 */

public class Demo10MapKeySet {
	
	public static void main(String[] args) {
		
		Map<Integer,Integer> map = new HashMap<>();
		map.put(1, 10);
		map.put(3, 30);
		map.put(2, 20);
		System.out.println(map);
		 
		//使用Set<K> keySet获取Map中的所有键值存到Set中
		Set<Integer> set = map.keySet();
		System.out.println(set);//[1, 2, 3]
		
		//遍历set获取map中的每一个key	使用迭代器或增强for循环
		//使用Map中的get(K)通过key找到value
		for(int key : set) {
			Integer v = map.get(key);
			System.out.println(v);
//			10
//			20
//			30
		}
		
	}

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

/*
 * Map 的第二种遍历方式,通过Map中的Entry对象遍历Map集合
 */

public class Demo11MapEntry {
	
	public static void main(String[] args) {
		//创建Map对象
		Map<Integer,Integer> map = new HashMap<>();
		map.put(1, 10);
		map.put(3, 30);
		map.put(2, 20);
		
		//使用Map中的Set<Map.Entry<K,V>> entrySet()将Entry对象存储到中
		Set<Entry<Integer, Integer>> set = map.entrySet();
		//遍历set获得Entry对象	使用迭代器或增强for循环
		//可以通过Entry的getKey和getValue获得key与value
		Iterator<Entry<Integer, Integer>> it = set.iterator();
		while(it.hasNext()) {
			Entry<Integer, Integer> e = it.next();
			System.out.println(e);//1=10	2=20	3=30
					
//			Integer k = e.getKey();
//			Integer v = e.getValue();
//			System.out.println(k + "=" + v);//1=10	2=20	3=30
		}
		
	}

}

HashMap存储自定义类型键值

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

public class Demo12HashMapSetPerson {
	
	public static void main(String[] args) {
		
		/*创建HashMap集合	
		 * key:String,不能重复,已经重写了hashCode和equals方法	 
		 * value:Person,可以重复
		 */
		HashMap<String, Person> map1 = new HashMap<String, Person>();
		map1.put("1", new Person("周老大",3));
		map1.put("2", new Person("周老二",2));
		map1.put("1", new Person("周老三",1));//key值重复,替换原value
		//遍历打印map1,使用keySet方法
		Set<String> set1 = map1.keySet();
		for(String key:set1) {
			Person value = map1.get(key);
			System.out.println(key+"--->"+value);
			/* 1--->Person [name=周老三, age=1]
			 * 2--->Person [name=周老二, age=2]
			 */
		}
		
		/*创建HashMap集合
		 * key:Person,不能重复,需要重写hashCode和equals方法
		 * value:String,可以重复
		 */
		HashMap<Person,String> map2 = new HashMap<>();
		map2.put(new Person("周老大",3), "1");
		map2.put(new Person("周老二",2), "2");
		map2.put(new Person("周老大",3), "3");//key值重复,替换原来的value
		//遍历打印map2,使用entrySet方法
		Set<Map.Entry<Person,String>> set2 = map2.entrySet();
		for(Map.Entry<Person, String> entry:set2) {
			Person key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key+"--->"+value);
			/* Person [name=周老大, age=3]--->3
			 * Person [name=周老二, age=2]--->2
			 */
		}
		
	}

}
public class Person {
	
	private String name;
	private int age;
	
	public Person() {
		
	}
	
	public Person(String name, int age) {
		this.name = name;
		this.age = 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;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + 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;
	}
	

}

LinkedHashMap集合

java.util.LinkedHashMap<K,V> extends HashMap<K,V>
Map接口的哈希表和链接列表实现,具有可预知的迭代顺序

底层原理:哈希表+链表(记录元素的顺序)

import java.util.LinkedHashMap;

public class Demo13LinkedHashMap {
	
	public static void main(String[] args) {
		
		//创建一个LinkedHashMap集合
		LinkedHashMap<Integer, String> linked = new LinkedHashMap<>();
		linked.put(3, "三");
		linked.put(1, "一");
		linked.put(1, "二");
		System.out.println(linked);//{3=三, 1=二}	有序,key值不允许重复
		
	}

}

Hashtable集合

java.util.Hashtable<K,V>集合 implements Map<K,V>接口

Hashtable集合底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢。
HashMap集合底层是一个哈希表,是一个线程不安全的集合,是多线程集合,速度快。

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

Hashtable和Vector集合一样,在jdk1.2之后被更先进的集合(HashMap、ArrayList)取代了。

Hashtable的子类Properties依然被使用,因为Properties集合是唯一一个与IO流相结合的集合。

JDK对集合添加的优化

List接口、Set接口、Map接口:里面添加了一个静态方法of,可以给集合一次性添加多个元素。

static<E> List<E> of(E...element)
【当集合中存储的元素个数已经确定了,不再改变时使用】

注意:

1.of方法只适用于List接口、Set接口、Map接口,不适用于接口的实现类。
2.of方法的返回值是一个不能改变的集合,集合不能再使用add和put方法添加元素,会出现异常(UnsupportedOperationException:不支持操作异常)
3.Set接口和Map接口在调用of方法的时候,不能有重复元素,否则会抛出异常(IllegalArgumentException:非法参数异常)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值