java 快速查找 list_JAVA 集合

1.1 使用集合框架的原因

因为传统的容器(数组)在进行增、删等破坏性操作时,需要移动元素,可能导致性能问题;同时添加、删除等算法和具体业务耦合在一起,增加了程序开发的难度。

因此,java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中。

1.2 Collection

Collection 是java 集合框架(collection-frame)中的顶层接口。

Collection 接口表示一个容器,容器中只能存储引用数据类型,建议存同一类型的引用类型,方便后续遍历等操作。

Collection 下面有两个接口 ,List 接口和 Set 接口。

List接口中的元素是有序的,可重复的;

Set接口中的元素是无序的,唯一的。

92b60cf1d9ff261540985e960d07c8e6.png

1.2.1 集合常用方法

public static void main(String[] args) {
		/**
		 * 增:add/addAll 删:clear/remove/removeAll/retainAll 改:
		 * 查:contains/containsAll/isEmpty/size
		 */
		Collection c1 = new ArrayList();
		c1.add("apple");// object obj = new String("apple");
		c1.add("banana");
		// c1.add(1); //object obj = new Integer(1);
		System.out.println(c1);

		// 追加一个集合
		Collection c2 = new ArrayList();
		c2.add("java");
		c2.add("c++");
		c1.addAll(c2);
		System.out.println(c1);

		// 删除集合中的所有元素
		// c1.clear();
		// System.out.println(c1);

		// 删除集合中指定位置上的元素 remove
		// c1.remove("apple");
		// System.out.println(c1);

		// 移除此集合中那些也包含在指定集合中的所有元素
		// c1.removeAll(c2);
		// System.out.println(c1);

		// 移除此集合中未包含在指定集合中的所有元素
		// c1.retainAll(c2);
		// System.out.println(c1);

		// 查找集合中是否包含此元素
		System.out.println(c1.contains("apple"));

		// 查找集合中是否包含此列表中的所有元素
		System.out.println(c1.containsAll(c2));

		// 检查集合是不是没有元素
		System.out.println(c1.isEmpty());

		// 返回集合元素的个数
		System.out.println(c1.size());

		// 判断两个集合元素是否相等
		System.out.println(c1.equals(c2));

	}

}

1.2.2 集合的遍历

Iterble 可遍历的接口。集合接口继承于它,支持快速遍历。

/**
		* 快速遍历 
		 * for - each 
		 * object 表示元素类型 
		 * item 表示迭代变量 
		 * c1 表示集合
		 */
		for (Object item : c1) {
			System.out.println(item.toString());
		}

快速遍历的本质

Collection 继承 Iterable 接口,表示集合支持快速遍历。Iteration 接口定义了一个方法 iterator() 用于获取集合的迭代器,是一个 Iteration 接口类型,iterator() 内部返回一个实现类实现Iteration 接口。这个实现类一定具有hasNext和next方法用于判断是否有下一个元素和获取下一个元素。快速遍历就是基于迭代器工作的。

0404761d162f1b0b8c09cfbdea3277bd.png
public static void main(String[] args) {
		Collection c1 = new ArrayList();
		c1.add("apple");
		c1.add("banana");
		c1.add("coco");
		c1.add("days");

		/**
		 * 快速遍历 
		 * for - each 
		 * object 表示元素类型 
		 * item 表示迭代变量 
		 * c1 表示集合
		 */
		for (Object item : c1) {
			System.out.println(item.toString());
		}
		// 常见的迭代器遍历
		Iterator it = c1.iterator();
		while (it.hasNext()) {
			Object item2 = it.next();
			System.out.println(item2.toString());
		}
		//大神的遍历方法
		for (Iterator it2=c1.iterator();it2.hasNext();) {
			Object item = it2.next();
			System.out.println(item.toString());
			
		}
	}

1.3 List 接口

List 接口中的元素是有序的、可重复的。List 接口中的元素通过索引(index)来确定元素的顺序。

有序的collection(也称为序列),可以对列表中的每个元素的插入位置进行精确的控制。

用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

1.3.1 List 常用方法

public static void main(String[] args) {
		/**
		 * 增:add/addAll/add(index,el)/addAll(index,collection)
		 * 删:clear/remove/removeAll/remove(index)
		 * 改:set(index,el)
		 * 查:get(index)/indexOf/lastIndexOf()
		 * 其他:contains/containsAll/isEmpty/size
		 */
		List list1 =  new ArrayList();
		//添加元素
		list1.add("apple");
		list1.add("banana");
		//在指定位置添加元素
		list1.add(0, "coco");
		System.out.println(list1);
		
		List list2 = new ArrayList();
		list2.add("java");
		list2.add("c++");
		//把list2的元素添加在list1中的指定位置
		list1.addAll(1, list2);
		System.out.println(list1);
		//删除指定位置的元素
		list1.remove(0);
		System.out.println(list1);
		//修改指定位置的元素
		list1.set(0, "js");
		System.out.println(list1);
		//查找指定位置的元素
		System.out.println(list1.get(0));
		//查找元素的位置
		System.out.println(list1.indexOf("js"));
		
		System.out.println(list1.lastIndexOf("banana"));
	}

1.3.2 List 接口遍历

ListIterator 继承于Iterator, 在Iterator 的继承上提供了以正向遍历集合,也可以以逆序遍历集合。

hasNext/next 以正向遍历

hasPrevious/previous 以逆序遍历

6897a987340c38460c9717c470010724.png
public static void main(String[] args) {
		List list1 = new ArrayList();
		list1.add("apple");
		list1.add("banana");
		list1.add("coco");
		//快速遍历
		System.out.println("--for each--");
		for (Object item : list1) {
			System.out.println(item.toString());
		}
		//普通for遍历
		System.out.println("--for--");
		for (int i = 0; i < list1.size(); i++) {
			System.out.println(list1.get(i));
		}
		//集合迭代器
		System.out.println("--iterator--");
		Iterator it = list1.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());			
		}
		//正向遍历
		System.out.println("--ListIterator--");
		System.out.println("--正向遍历--");
		ListIterator it2 = list1.listIterator();
		while (it2.hasNext()) {
			System.out.println(it2.next());			
		}
		//逆序遍历
		System.out.println("--逆序遍历--");
		while (it2.hasPrevious()) {
			System.out.println(it2.previous());	
			
		}
                //从列表的指定位置开始遍历
		System.out.println("--从列表的指定位置开始遍历--");
		ListIterator it3 = list1.listIterator(2);
		while (it3.hasNext()) {
			System.out.println(it3.next());
			
		}
	}

1.4 数据结构

数据结构就是数据在内存中存储结构。根据存储的方式不同,分为线性表、二叉树、图、栈、队列等。

1.4.1 线性表

线性表数据结构是按照一定的逻辑顺序存储在内存中。线性表是有序的。线性表根据内存的物理结构分为两种:数组和链表。

数组是一种逻辑上有序的线性表,物理上也连续。

1910235cb0fe2f602fd425f9db74bf8f.png

链表是一种逻辑上有序的线性表,但物理上不连续。

53efcc35021d8d1875015bce97bc4b9f.png

数组和链表的区别

数组在查询是效率高,在添加、删除元素时效率低(涉及移动元素);

链表在查询时效率低(每次从头开始,不能跳跃访问),在添加、删除元素时效率高(不涉及移动元素)。

1.4.2 栈

特性:先进先出,后进后出。

6e3cd29e14526d8456a373d87e4c8cff.png

1.4.3 队列

特性:先进先出。

8bc53f9aae7ec85c13c8b6c60a422a75.png

1.5 ArrayList/Vector

1.ArrayList

ArrayList 是 List 接口的实现类,底层数据结构是数组,可以实现大小可变的数组。

ArrayList 线程不安全 ,jdk1.2。

ArrayList 底层数据结构是数组,默认数组大小是10,如果添加的元素个数超过默认容量,ArrayList 会自动扩容,扩容原则:newCapacity = oldCapacity + oldCapacity/2;

如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。

ArrayList 作为List 接口的实现类,常用方法和遍历参考List接口。

2.Vector

Vector 是List 接口的实现类,底层数据结构也是数组,也是大小可变的数组。

Vector 是线程安全的,jdk1.0。

Vector 底层数据结构是数组,默认数组大小是10,如果添加的元素个数超过默认容量,Vector 会自动扩容,扩容原则:newCapacity = oldCapacityIncrement(增长因子);如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。

注意:Vector 在实现List接口的同时,添加了自身特有的方法xxxElement,未来使用时为了程序的可拓展性,一定要按照接口来操作Vector。

1.6 LinkedList

LinkedList 是 List 接口的实现类,底层数据结构是链表。

LinkedList 常用方法和遍历方法参照List 接口。

LinkedList 线程不安全。

除了实现List接口,还实现了栈接口

d34a054ecc8e4446b34033d770c2ade6.png

push入栈操作 / pop 出栈操作

public class Test01 {
	public static void main(String[] args) {
		LinkedList list = new LinkedList();
		list.push("apple");
		list.push("banana");
		list.push("coco");
		
		System.out.println(list.pop());
		System.out.println(list.pop());
		System.out.println(list.pop());
		
		
	}
}

队列(Queue)接口

894737835f9d29b4cb954267fe5dde87.png

add/remove/element( ) 可能会出现 NoSuchElementException 异常。

public class Test02 {
	public static void main(String[] args) {
		LinkedList queue = new LinkedList();
		queue.add("apple");
		queue.add("banana");
		queue.add("coco");
		
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		System.out.println(queue.remove());
		
		// 获取表头元素
		System.out.println(queue.element());
	}

}

offer/poll/peek 可能会返回特殊值(null)

public static void main(String[] args) {
		LinkedList queue = new LinkedList();
		//入队
		queue.offer("apple");
		queue.offer("banana");
		queue.offer("coco");
		//出队
		System.out.println(queue);
		//获取表头元素
		System.out.println(queue.peek());
	}

双向队列(Deque)接口

f6ea814437add3417321f08e52bc666b.png
public static void main(String[] args) {
		LinkedList queue = new LinkedList();
		queue.addFirst("apple");
		queue.addFirst("banana");
		queue.addFirst("coco");
		
		System.out.println(queue);
		//获取并移除此双端队列的最后一个元素。
		System.out.println(queue.removeLast());
		//获取并移除此双端队列的第一个元素。
		System.out.println(queue.removeFirst());
		
		System.out.println(queue);
		//获取表头元素
		System.out.println(queue.getFirst());
		
	}

1.7 Iterator 和 ListIterator

Iterator 在迭代过程中不允许向集合中添加元素。

public static void main(String[] args) {
		ArrayList list = new ArrayList();
		list.add("apple");
		list.add("banana");
		list.add("coco");
		
		Iterator it = list.iterator();
		while(it.hasNext()) {
			String item = (String) it.next();
			if(item.equals("banana")) {
				list.add("test");
			}
		}
		
		System.out.println(list);
	}

当通过Iterator集合迭代器遍历集合过程中,不能再向集合汇总添加元素,否则出现ConcurrentModificationException 并发修改异常。

ListIterator允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。

public class Test01 {
	public static void main(String[] args) {
		ArrayList list = new ArrayList();
		list.add("apple");
		list.add("banana");
		list.add("coco");
		
		ListIterator it = list.listIterator();
		while(it.hasNext()) {
			String item = (String) it.next();
			if(item.equals("banana")) {
				it.add("test");
			}
		}
		
		System.out.println(list);
	}
}

1.8 泛型(generic)

1.8.1 泛型的概念

泛型允许开发者在强类型程序设计语言(java)编写代码时定义一些可变部分,这些部分在使用前必须做出指明。

泛型就是将类型参数化

b31f478c858f4f22855b8f4d133b5420.png

1.8.2 泛型的擦除

泛型在编译器起作用。因为在运行时泛型就被擦除了 ,所以 jvm 察觉不到泛型的存在。

public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<String>();
		list.add("apple");
		System.out.println(list instanceof ArrayList);
		System.out.println(list instanceof ArrayList<String>);
}

运行后的结果

Cannot perform instanceof check against parameterized type ArrayList<String>. 
Use the form ArrayList<?> instead since further generic type information will 
be erased at runtime

1.8.3 泛型的应用

1.8.3.1 泛型类

当一个类中属性的数据类型不确定时,具体使用什么类型由使用者决定时,使用泛型。泛型类的形式。

public class 类名<T> {
    
}

定义一个泛型类

public class FanClass<T> {
	private T t;

	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}

	public FanClass() {
		super();
	}

	public FanClass(T t) {
		super();
		this.t = t;
	}
public class Test01 {
	public static void main(String[] args) {
		FanClass<String> fan = new FanClass<String>();
		fan.setT("banana");
		
	}

1.8.3.2 泛型方法

当一个方法的参数类型不确定时,具体是什么类型由使用者来确定,可以考虑使用泛型方法。形式:

public class Student {
	//定义一个泛型类型
	public <T> void showInfo(T a){
		System.out.println(a);
	}
	//定义多个泛型类型
	public <A,B> void showInfo2(A b,B c){
		System.out.println(b);
		System.out.println(c);
		}
	//定义多个同类型的泛型
	public <String> void print( String...d){
		System.out.println(d);
	}

}
public static void main(String[] args) {
		FanClass<String> fan = new FanClass<String>();
		fan.setT("banana");
		
		Student stu = new Student();
		stu.showInfo(1);
		stu.showInfo(1.0f);
		stu.showInfo("apple");
		
		stu.showInfo2(2, "banana");
		
		stu.print("1,2,3");
		stu.print("4,5,6");
	}

泛型方法在调用时确定(指明)类型。

泛型方法在一定程度上优化了方法重载。

泛型方法可以定义多个泛型类型,还可以定义多个同类型的泛型类型。

1.8.3.3 泛型接口

如果接口中的方法的参数(形参、返回值)不确定时,可以考虑使用泛型接口。形式如下

public interface FanInterface<T> {
	public void showInfo(T t);

}

1.实现类能确定泛型接口的类型

public class ImpIclass implements FanInterface<String>{

	@Override
	public void showInfo(String t) {
		// TODO Auto-generated method stub
		
	}
}

2.实现类不能确定泛型接口的类型(继续泛型)

public class ImplClass2<T> implements FanInterface<T> {

	@Override
	public void showInfo(T t) {
		// TODO Auto-generated method stub
		
	}

}

1.8.3.4 泛型的上限和下限

public static void print(ArrayList<? extends Pet> list) {
		for (Pet pet : list) {
			pet.showInfo();
		}
	}

泛型的上限ArrayList(? extends Pet) list 声明了一个容器,容器中的元素类型一定要继承于Pet,我们称这种形式叫做泛型的上限。

泛型的下限ArrayList(? super Pet) list 声明了一个容器,容器中的元素类型一定要是Pet的父类,我们称这个形式为泛型的下限。

1.9 Set 接口

Set 接口表示一个唯一、无序的容器(和添加顺序无关)

1.9.1 Set 接口提供的方法

public static void main(String[] args) {
		/**
		 * 增:add/addAll
		 * 删:clear/remove/removeAll/retainAll
		 * 改:
		 * 查:contains/containsAll
		 * 遍历:iterator
		 * 其他:size/isEmpty
		 */
		
		Set<Integer> set = new HashSet<Integer>();
		// [1]添加
		// 无序
		set.add(10);
		set.add(3);
		set.add(20);
		set.add(0);
		// 不能添加重复元素
		boolean r = set.add(1);
		System.out.println(set);
		
		// 【2】删除
//		set.remove(1);
//		set.clear();
//		System.out.println(set);
		
		// 【3】查看是否包含
		System.out.println(set.contains(1));
		
		// 【4】其他
		System.out.println(set.size());
		System.out.println(set.isEmpty());
	}

1.9.2 Set 接口的遍历

public static void main(String[] args) {
		
		Set<String> set = new HashSet<String>();
		set.add("banana");
		set.add("apple");
		set.add("coco");
		
		// 快速遍历
		for (String item : set) {
			System.out.println(item);
		}
		
		// 迭代器
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String item = it.next();
			System.out.println(item);
		}
	}

Set 接口的实现类常见的有 HashSet 、LinkedHashSet 、TreeSet。

1.10 HashSet

HashSet 是 Set 接口的实现类,底层数据结构是哈希表。

HashSet 是线程不安全的(不保证同步)

1.10.1 哈希表工作原理

e4f75373dbf2018785b982f8269e12c7.png

1.10.2 添加自定义对象

根据哈希表的工作原理,请存储一个自定义对象到HashSet 中。

package cn.qjp03.hashset;

public class Student {
	private String id;
	private String name;
	private int age;

	// …
	

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((id == null) ? 0 : id.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;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			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 "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

}

总结

[1]如果向HashSet中存储元素时,元素一定要实现hashCode方法和equals方法。

[2] 优点:添加、删除、查询效率高;缺点:无序。

1.11 LinkedHashSet

LinkedHashSet 是Set接口的实现类,底层数据结构哈希表+链表

哈希表用于散列元素;链表用于维持添加顺序。

如果要添加自定义对象元素,也需要重写hashCode 和 equals 方法。

1.12 TreeSet

TreeSet 是Set 接口的实现类,底层数据结构是二叉树。

TreeSet 存储的数据按照一定的规则存储,存储规则让数据表现出自然顺序。

1.12.1 TreeSet 工作原理

53dd69378b99d88f67b62422ef00675b.png

添加一个新元素t的存储的步骤

[1] 如果集合无元素,t直接加入;如果集合有元素,t和根节点比较;

[2] 如果t小于根节点;把t放到根节点的左子树上;重复1-3步骤

[3] t大于根节点;把t放到根节点的右子树上;重复1-3步骤

输出时按照一定的规则:左子树->根节点->右子树

根据TreeSet的工作原理,向TreeSet添加自定义元素?

向TreeSet中添加元素时,一定要提供比较策略,否则会出现ClassCastException。

比较策略分两种:内部比较器和外部比较器

1.12.2 内部比较器

当一个自定义对象实现Comparable 并实现 compareTo 方法时,通过指定具体的比较策略,此时称为内部比较器。

package cn.sxt05.treeset;

public class Student implements Comparable<Student>{
	private String id;
	private String name;
	private int age;

	// 。。。

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

	@Override
	public int compareTo(Student o) {
		if(this.getAge()<o.getAge()) {
			return -1;
		}else if(this.getAge() == o.getAge()) {
			return 0;
		}else {
			return 1;
		}
	}

}

比较策略的几种情况

1.比较策略一般是当前队象写在前面,待比较对象写在后面,比较结果默认升序

return  this.getAge() - o.getAge() ;

如果想要降序,改变两个比较对象的位置即可。

2.多种比较因素

@Override
	public int compareTo(Student o) {
		/*if(this.getAge()<o.getAge()) {
			return -1;
		}else if(this.getAge() == o.getAge()) {
			return 0;
		}else {
			return 1;
		}*/
		
		// return  this.getAge() - o.getAge() ;
		
		if(this.getAge()<o.getAge()) {
			return -1;
		}else if(this.getAge() == o.getAge()) {
			return this.getName().compareTo(o.getName());
		}else {
			return 1;
		}
	}

1.12.3 外部比较器

当实际开发过程中不知道添加元素的源代码、无权修改别人的代码,此时可以使用外部比较器。

Comparator 位于java.util包中,定义了compare(o1,o2) 用于提供外部比较策略。

TreeSet接受一个指定比较策略的构造方法,这些比较策略的实现类必须实现Comparator

接口。

需求:按照字符串的长度比较

public class Test01 {
	public static void main(String[] args) {
		
		LenComparator lenComparator = new LenComparator();
		TreeSet<String> set2 = new TreeSet<String>(lenComparator);
		
		set2.add("banana");
		set2.add("coco");
		set2.add("apple");
		
		set2.add("apple");
		System.out.println(set2);
		
	}
}

class LenComparator implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		return o1.length() - o2.length();
	}	
}

使用匿名内部类优化

public class Test02 {
	public static void main(String[] args) {
		
		TreeSet<String> set2 = new TreeSet<String>(new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
			
		});
		
		set2.add("banana");
		set2.add("coco");
		set2.add("apple");
		
		set2.add("apple");
		System.out.println(set2);
		
	}
}

1.13 Map 接口

Map接口称为键值对集合或者映射集合,其中的元素(entry)是以键值对(key-value)的形式存在。

Map 容器接口中提供了增、删、改、查的方式对集合进行操作。

Map接口中都是通过key来操作键值对,一般key是已知。通过key获取value。

1.13.1 map 常用方法

public static void main(String[] args) {
		
		/**
		 * 增:put/putAll
		 * 删:clear/remove
		 * 改:put
		 * 查:get/containsKey/containsValue
		 * 其他:isEmpty/size
		 */
		
		Map<String, String> map = new HashMap<String,String>();
		
		// 【1】put
		map.put("A", "apple");
		map.put("B", "banana");
		map.put("C", "coco");
		
		// 【2】删除
		// map.clear();
		// smap.remove("A");
		
		// 【3】修改
		//map.put("A", "apple x");
		
		// 【4】查看
		String val = map.get("A");
		System.out.println(map.containsKey("D"));
		
		
		System.out.println(map);
	}

1.13.2 map 接口的遍历

通过keySet() 返回map中键的set集合。

public static void main(String[] args) {

		Map<String, String> map = new HashMap<String,String>();
		
		map.put("B", "banana");
		map.put("A", "apple");
		map.put("C", "coco");
		// map无序
		// 可以根据key的自然顺序 让map有序  => 一般用string作为key
		System.out.println(map);
		
		
		// 遍历
		Set<String> keys = map.keySet();
		for (String key : keys) {
			System.out.println(key+"=>"+map.get(key));
		}
		
		Iterator<String> it = keys.iterator();
		while(it.hasNext()) {
			String key = it.next();
			System.out.println(key+"=>"+map.get(key));
		}
	}

map中以键值对作为元素,键值对在map中称为entry,entrySet返回键值对的set集合。

public static void main(String[] args) {

		Map<String, String> map = new HashMap<String,String>();
		
		map.put("B", "banana");
		map.put("A", "apple");
		map.put("C", "coco");
		// map无序
		// 可以根据key的自然顺序 让map有序  => 一般用string作为key
		System.out.println(map);
		
		// entrySet
		Set<Entry<String, String>> entrySet = map.entrySet();
		for (Entry<String, String> entry : entrySet) {
			System.out.println(entry.getKey()+"=>"+entry.getValue());
		}
		
		Iterator<Entry<String, String>> it2 = entrySet.iterator();
		while(it2.hasNext()) {
			Entry<String, String> entry = it2.next();
			System.out.println(entry.getKey()+"=>"+entry.getValue());
		}
	}

Map接口的实现类HashMap、LinkedHashMap、TreeMap

1.14 HashMap

HashMap 是Map的实现类,Key 以HashMap 存储。

public static void main(String[] args) {
		
		/*
		HashMap<String, Object> map = new HashMap<String,Object>();
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1.add("alex");
		list1.add("alice");
		list1.add("allen");
		map.put("A", list1);
		
		
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("ben");
		list2.add("bill");
		map.put("B", list2);
		
		System.out.println(map);
		*/
		
		
		HashMap<Student, Object> map = new HashMap<Student,Object>();
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1.add("alex");
		list1.add("alice");
		list1.add("allen");
		Student s1 = new Student("001", "大狗", 20);
		map.put(s1, list1);
		
		
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("ben");
		list2.add("bill");
		Student s2 = new Student("001", "大狗", 20);
		// 修改
		map.put(s2, list2);
		System.out.println(map);
		
	}

总结:

[1] 向HashMap中存储元素时,key一定要实现hashCode和equals

[2] 一般建议使用String作为Map接口的key

1.15 LinKedHashMap

LinkedHashMap是Map接口的实现类,key以LinkedHashSet存储。

哈希表散列key,链表维持key的添加顺序。

public static void main(String[] args) {
		
		
		/*LinkedHashMap<String, Object> map = new LinkedHashMap<String,Object>();
		
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("ben");
		list2.add("bill");
		map.put("B", list2);
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1.add("alex");
		list1.add("alice");
		list1.add("allen");
		map.put("A", list1);
		
		System.out.println(map);*/
		
		
		
		HashMap<Student, Object> map = new HashMap<Student,Object>();
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1.add("alex");
		list1.add("alice");
		list1.add("allen");
		Student s1 = new Student("001", "大狗", 20);
		map.put(s1, list1);
		
		
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("ben");
		list2.add("bill");
		Student s2 = new Student("001", "大狗", 20);
		// 修改
		map.put(s2, list2);
		System.out.println(map);
		
	}

1.16 TreeMap

TreeMap是Map的实现类,key以TreeSet存储。

public static void main(String[] args) {
		
		
		/*TreeMap<String, Object> map = new TreeMap<String,Object>(new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
		});
		
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("ben");
		list2.add("bill");
		map.put("Aa", list2);
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1.add("alex");
		list1.add("alice");
		list1.add("allen");
		map.put("B", list1);
		
		System.out.println(map);*/
		
		
		
		TreeMap<Student, Object> map = new TreeMap<Student,Object>(new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				return o1.getAge() - o2.getAge();
			}
		});
		
		ArrayList<String> list1 = new ArrayList<String>();
		list1.add("alex");
		list1.add("alice");
		list1.add("allen");
		Student s1 = new Student("001", "大狗", 20);
		map.put(s1, list1);
		
		
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("ben");
		list2.add("bill");
		Student s2 = new Student("001", "2狗", 20);
		// 修改
		map.put(s2, list2);
		System.out.println(map);
		
	}

1.17 总结

745f0077a1b14f003c79be1771761b70.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值