LinkedList、Set和Map

LinkedList,Set和Map

1. LinkedList

1.1 LinkedList 介绍
底层数据存储结构为双向链表
链表头:
	class LinkedList<E> {
		Node<E> first;
		Node<E> last;
		int size;
	}
	
	Node 是 LinkedList 内部类!!!

节点 Node<E>
	class Node<E> {
		Node<E> previous; // 引用 指向前一个节点 Node 引用
		E e;
		Node<E> next; // 引用  指向后一个节点 Node 引用
	}
1.2 图例分析 LinkedList

1.3 重要方法演示
package com.qfedu.a_linkedlist;

import java.util.LinkedList;

/*
 * LinkedList<E> 方法演示
 * 
 * addFirst(E e); 添加元素到头节点之前
 * addLast(E e); 添加元素到尾节点之后
 * E getFirst(); 获取头节点元素
 * E getLast(); 获取尾节点元素
 * E removeFirst(); 删除头节点元素,返回值是头节点元素数据内容
 * E removeLast(); 删除尾节点元素,返回值是尾节点元素数据内容
 */
public class Demo1 {
	public static void main(String[] args) {
		LinkedList<String> list1 = new LinkedList<String>();

		list1.add("胡辣汤");
		list1.add("小米粥");
		list1.add("豆腐脑");
		list1.add("两掺");
		
		System.out.println(list1);
		
		list1.addLast("牛肉包子");
		list1.addFirst("牛肉肉盒");
		
		System.out.println(list1); 
		
		System.out.println(list1.getFirst());
		System.out.println(list1.getLast());
		
		System.out.println(list1.removeFirst());
		System.out.println(list1.removeLast());
		
		System.out.println(list1);
	}
}

2. Set

2.1 Set集合概述
特征:
	无序 数据存储顺序和添加顺序不一致。
	不可重复 要求元素存储不允许出现相同元素,如果添加相同元素,add方法返回值为 false
Set集合没有特征方法,使用的方法都是 Collection 方法
class HashSet<E>
class TreeSet<E>
package com.qfedu.b_set;

import java.util.HashSet;

public class Demo1 {
	public static void main(String[] args) {
		HashSet<Integer> set = new HashSet<Integer>();
		
		/*
		 * 无序 : 数据存储顺序和添加顺序不一致。
		 */
		set.add(2);
		set.add(6);
		set.add(1);
		set.add(4);
		set.add(5);
		set.add(3);
		
		System.out.println(set);
		
		HashSet<String> set2 = new HashSet<String>();
		
		set2.add("羊肉汤");
		set2.add("烩面");
		set2.add("牛肉面");
		set2.add("葱油拌面");
		set2.add("炒拉条");
		/*
		 * 不可重复,要求元素存储不允许出现相同元素,如果添加相同元素,add方法返回值为 false
		 */
		System.out.println(set2.add("油泼面"));
		System.out.println(set2.add("油泼面"));
		
		System.out.println(set2);
	}
}

2.2 HashSet 存储流程概述分析
底层数据存储结构为 哈希表结构 ==> 简单来看就是一个 Excel 表格。
HashSet 存储数据主要有两个过程
	1. 通过添加元素的 hashCode 方法获取添加元素的 哈希值,通过 哈希运算 计算当前元素应该在哈希表中对应单元格位置
	2. 如果对应单元格存在其他元素,需要通过调用 equals 方法判断两个元素是否同一个元素,如果是同一个元素,后者无法添加,如果不一致,可以存储。
package com.qfedu.b_set;

import java.util.HashSet;

public class Demo2 {
	public static void main(String[] args) {
		HashSet<Person> set = new HashSet<Person>();

		/*
		 * 执行添加方法,都会自动调用添加元素的 hashCode 方法
		 */
		set.add(new Person(1, "张三", 26));
		set.add(new Person(2, "李四", 26));
		set.add(new Person(3, "王乾", 96));
		set.add(new Person(4, "王某平", 86));
		set.add(new Person(5, "玮豪哥哥", 76));
		set.add(new Person(6, "周董", 66));
		/*
		 * 第二次添加 new Person(6, "周董", 66)
		 * 在当前 Set 集合中有相同元素,添加失败。
		 * 1. 添加元素过程中,调用hashCode方法,计算对应单元格位置,发现对应单元格有之前添加的元素
		 * 2. 调用添加元素的 equals 方法,和之前元素比较,如果比较结果为同一个元素,根据 Set 集合规则
		 * 无法存在相同元素,添加失败
		 */
		set.add(new Person(6, "周董", 66));
		Person p1 = new Person(6, "周董", 66);
		Person p2 = new Person(6, "周董", 66);
		System.out.println(p1.hashCode());
		System.out.println(p2.hashCode());

		System.out.println(set);
		System.out.println(set.size());
	}
}
2.3 TreeSet 结构分析和存储数据要求

package com.qfedu.b_set;

/*
 * 自定义类遵从 Comparable 接口,增强为一个可比较类!!!
 * 采用的遵从方式是【妻管严模式】在遵从接口的过程中,直接明确当前泛型约束
 * 数据类型为 SingleDog 类型,当前类为 SingleDog 所需进行比较的类型
 * 也是对应 SingleDog 类型,非其他类型。
 */
public class SingleDog implements Comparable<SingleDog> {
	private int id;
	private String name;
	private int age;

	public SingleDog() {
	}

	public SingleDog(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	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 "SingleDog [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

	/*
	 * 遵从 Comparable<T> 接口要求实现的方法
	 * 返回值为 int 类型
	 * 		返回值为 0 两者一致 ==> 利用到 TreeSet(底层数据存储为二叉树的 Set 集合) 无法添加后者元素
	 * 		返回值为 正/负数 存在大小比较关系。
	 */
	@Override
	public int compareTo(SingleDog o) {
		System.out.println("遵从 Comparable 接口实现 compareTo 方法");
		/*
		 * age 调用方法对象对应的 age 成员变量
		 * o.age 是参数对象对应的 age 成员变量
		 * 调用方法对象和参数对象不重要!!!完全由 TreeSet(底层数据存储为二叉树的 Set 集合) 自行决定!!!
		 */
		return o.age - age;
	}

}

package com.qfedu.b_set;

/*
 * 自定义类遵从 Comparable 接口,增强为一个可比较类!!!
 * 采用的遵从方式是【妻管严模式】在遵从接口的过程中,直接明确当前泛型约束
 * 数据类型为 SingleDog 类型,当前类为 SingleDog 所需进行比较的类型
 * 也是对应 SingleDog 类型,非其他类型。
 */
public class SingleDog implements Comparable<SingleDog> {
	private int id;
	private String name;
	private int age;

	public SingleDog() {
	}

	public SingleDog(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	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 "SingleDog [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

	/*
	 * 遵从 Comparable<T> 接口要求实现的方法
	 * 返回值为 int 类型
	 * 		返回值为 0 两者一致 ==> 利用到 TreeSet(底层数据存储为二叉树的 Set 集合) 无法添加后者元素
	 * 		返回值为 正/负数 存在大小比较关系。
	 */
	@Override
	public int compareTo(SingleDog o) {
		System.out.println("遵从 Comparable 接口实现 compareTo 方法");
		/*
		 * age 调用方法对象对应的 age 成员变量
		 * o.age 是参数对象对应的 age 成员变量
		 * 调用方法对象和参数对象不重要!!!完全由 TreeSet(底层数据存储为二叉树的 Set 集合) 自行决定!!!
		 */
		return o.age - age;
	}

}
package com.qfedu.b_set;

import java.util.Comparator;

/**
 * 自定义比较器类,遵从 Comparator 接口,同时泛型直接约束确定为 SingleDog类型
 * 当前自定义比较器是处理比较 SingleDog 类型的
 * @author Anonymous
 *
 */
public class MyComparator implements Comparator<SingleDog> {

	/*
	 * 返回值为 int 类型
	 * 		返回值为 0 两者一致 ==> 利用到 TreeSet(底层数据存储为二叉树的 Set 集合) 无法添加后者元素
	 * 		返回值为 正/负数 存在大小比较关系。
	 */
	@Override
	public int compare(SingleDog o1, SingleDog o2) {
		System.out.println("自定义比较器遵从 Comparator 接口,实现 compare 方法");
		return o1.getAge() - o2.getAge();
	}
}

3. Map

3.1 Map 双边队列
键值对 Key = Value
例如:
	{name:张三, age:16, gender:男, address=河南省郑州市二七区航海中路60号}
	==>
	Person类 
	{name:张三, name:张四} 类似于 一个类内有两个同名的成员变量???是否允许出现???

针对于 键值对模型
	Key 是在整个数据中唯一的
	value 是对应key 且允许 value 重复

Java 中利用 interface Map<K, V> 用于对应键值对模型数据,而且在开发中大量使用。
	K key V Value 
	Map 结构使用两个泛型,一个 K 约束 键 V 约束 值

Map整体Java体系
interface Map<K, V>
--| class HashMap<K, V> 
	底层数据存储方式为 哈希表结构的 Map 双边队列,对于整个数据而言 Key 唯一,采用 Key 对应数据哈希值决定当前【键值对】在哈希表中的存储位置。

--| class TreeMap<K, V>	
	底层数据存储结构为 平衡二叉树结构,也是根据对应整个Map 唯一的 Key ,要求Key有比较顺序或者提供对应的比较方式。Comparator 接口 Comparable 接口
3.2 Map 双边队列涉及到的方法【抄十遍】
增
	put(K k, V v);
		根据实例化 Map 双边队列对象约束的键值对泛型类型,添加对应的键值对
	putAll(Map<? extends K, ? extends V> map);
		添加参数 Map 双边队列到当前 Map 中,要求参数Map数据存储类型和调用方法 Map 存储数据类型一致或者其子
		类
删
	V remove(Object key);
		根据指定 Key 删除对应的键值对对象,返回值是对应的 Value 数据
改	
	put(K k, V v);
		如果当前 Map 双边队列中有对应 Key ,使用当前参数 value 替换原 Map 存储 value
查
	int size();
		Map双边队列中有效键值对个数
	boolean isEmpty();
		判断当前 Map 双边队列是否为空
	boolean containsKey(Object key);
		判断当前 Map 双边队列中,是否有指定 Key 存在
	boolean containsValue(Object value);
		判断当前 Map 双边队列中,是否有指定 Value 存在
    Collection<V> values();
    	返回整个 Map 双边队列所有 Value 对应的 Collection<V>
    Set<K> keySet();
		返回整个 Map 双边队列所有 Key 对应的 Set<K> 集合

tips: 不需要抄
	方法结尾为 Set 返回值类型是 Set 集合
	方法结尾为对应单词的复数 例如: s es ies 返回值类型一般是 数组类型,List 集合,Collection 集合
3.3 重点方法 entrySet 方法
Map<K, V> ==> K, V ==> Entry对象
Set<Map.Entry<K, V>> entrySet();
	通过 Map 双边队列对象,获取当前 Map 双边队列的所有键值对(Entry类型) Set 集合。

Entry 是 Map 内部类	
	对应当前 Map 双边队列的 键值对对象(Key=Value) ==> Entry
	Entry 在整个 Map 双边队列中不可重复,可以通过 entrySet方法 获取得到整个 Map 双边队列的所有键值对对象 Entry 对应的 Set 集合
	class Entry<K, V> {
		K k;
		V v;
		
		public K getKey() {
			return k;
		}
		
		public V getValue() {
			return v;
		}
	}
例如:
	Map<String, Integer> map ==> {"宫保鸡丁":15, "老干妈":10};
	Set<Entry<String, Integer>> set = map.entrySet();
	set<Entry> ===> {
		Entry<String, Integer> => {K:"宫保鸡丁", V:15},
		Entry<String, Integer> => {K:"老干妈", V:10}
	}
package com.qfedu.c_map;

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

/*
 * EntrySet 方法
 */
public class Demo2 {
	public static void main(String[] args) {
		HashMap<String, Integer> map1 = new HashMap<String, Integer>();

		map1.put("宫保鸡丁", 15);
		map1.put("羊肉烩面", 12);
		map1.put("班记油泼面", 15);
		map1.put("羊肉泡馍", 20);
		map1.put("黄焖鸡米饭", 16);
		map1.put("驴肉火烧", 8);
		
		Set<Entry<String, Integer>> entrySet = map1.entrySet();
		
		for (Entry<String, Integer> entry : entrySet) {
			System.out.print(entry.getKey() + ":");
			System.out.println(entry.getValue());
		}
	}
}

posted @ 2022-05-15 23:50  qtyanan  阅读(31)  评论(0编辑  收藏  举报