前言:
Java的类集框架比较多,也十分重要,在这里给出图解,能够理解为相应的继承关系,也能够看成重要知识点回顾;html
Collection集合接口
继承自:Iterablejava
public interface Collection<E> extends Iterable<E>
java.util.Collection
是单值集合操做的最大父接口,其中有几个核心操做方法以及经常使用操做方法;
python
boolean |
add(E e) |
确保此集合包含指定的元素(可选操做)。 |
boolean |
addAll(Collection<? extends E> c) |
将指定集合中的全部元素添加到此集合(可选操做)。 |
void |
clear() |
从集合中删除全部元素(可选操做)。 |
boolean |
contains(Object o) |
若是该集合包含指定的元素,则返回true。 |
boolean |
remove(Object o) |
若是存在,则今后集合中删除指定元素的单个实例(可选操做)。 |
int |
size() |
返回此集合中的元素数。 |
Object[] |
toArray() |
返回一个包含此集合中全部元素的数组。 |
Iterator<E> |
iterator() |
返回对此集合中的元素进行迭代的迭代器。 |
上面方法中有两个特殊的方法就是cotains
与remove
;都须要equals
方法的支持才能删除与查询数据;不然找不到元素。web
后面都是衍生出的子类方法。数组
List集合
最大特色:容许保存重复的元素,并在其父接口上扩充了其余的方法;安全
继承关系:微信
public interface List<E> extends Collection<E>
void |
add(int index, E element) |
Inserts the specified element at the specified position in this list (optional operation). |
boolean |
add(E e) |
Appends the specified element to the end of this list (optional operation). |
ListIterator<E> |
listIterator() |
Returns a list iterator over the elements in this list (in proper sequence). |
static <E> List<E> |
of() |
Returns an unmodifiable list containing zero elements. |
default void |
forEach(Consumer<? super T> action) |
Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception. |
实例:并发
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.List;
public class 多数据保存 {
public static void main(String[] args) {
List<String> all = List.of("xbhg","Hello","World","welcome");
Object[] result = all.toArray();
for (Object t: result) {
System.out.println(t);
}
System.out.println("----------分割线----------");
all.forEach(System.out::println); //方法引用部分的引用构造方法
}
}
ArrayList子类
继承结构以下:app
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
实例化:重复元素容许保存而且按照添加时的顺序保存;框架
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayList实例化List {
public static void main(String[] args) {
List<String> all = new ArrayList<String>();
all.add("Hello");
all.add("你好");
all.add("你好");
all.add("xbhog");
System.out.println(all);
all.forEach(System.out::print);
//lambda表达式
all.forEach((str)->{
System.out.print(str+"、");
});
}
}
集合操做方法:
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.ArrayList;
import java.util.List;
public class ArrayLIst集合相关操做 {
public static void main(String[] args) {
List<String> all = new ArrayList<String>();
System.out.println("集合是否为空?"+all.isEmpty()+"、集合元素个数"+all.size());
all.add("1");
all.add("2");
all.add("3");
System.out.println("集合是否为空?"+all.isEmpty()+"、集合元素个数"+all.size());
System.out.println(all.get(1));
System.out.println(all.remove("3"));
System.out.println("集合是否为空?"+all.isEmpty()+"、集合元素个数"+all.size());
}
}
ArrayList原理分析:重点
首先须要明确ArrayList是经过数组实现的;这样就出现了ArrayList经过什么样的方式进行的扩容操做,以及在什么状况下才会扩容?
ArrayList类中的数组是在构造方法中进行的空间开辟的;其对应的有无参和有参构造方法:
无参构造方法:使用空数组(长度为0)初始化,在第一次使用时会为其开辟空间为(初始化程度为10);
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//默认的开辟空间大小
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
有参构造方法:长度大于0则以指定长度开辟数组空间;若是长度为0,则按照无参构造方法进行;若是负数则抛出ILLegaLArgumentException异常;
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
当数组扩充后利用数组复制的形式,将旧数组中的数据复制到开辟的新数组中;
其最大程度为:
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
ArrayList保存自定义类对象:
该操做必然包含了相关的增删改查;因为contains与remove方法的实现都须要经过对象比较俩完成;因此咱们须要覆写equals方法
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.ArrayList;
import java.util.List;
class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public boolean equals(Object obj){
if(this== obj) return true;
if(obj == null) return false;
if(!(obj instanceof Person)) return false;
Person pe = (Person) obj;
return this.name.equals(pe.name) && this.age == pe.age;
}
@Override
public String toString() {
return "姓名:"+this.name +"、年龄:"+this.age;
}
}
public class ArrayList保存自定义类对象 {
public static void main(String[] args) {
List<Person> std = new ArrayList<Person>();
std.add(new Person("xbhog",1));
std.add(new Person("小明",2));
std.add(new Person("小白",3));
System.out.println("-------删除前的数据内容----------");
std.forEach((person)->{
System.out.println("姓名:"+person.getName()+"、年龄:"+person.getAge());
});
System.out.println("-------删除后的数据内容----------");
std.remove(new Person("小白",3));
std.forEach((person)->{
System.out.println("姓名:"+person.getName()+"、年龄:"+person.getAge());
});
System.out.println("-------查看数据是否存在----------");
System.out.println(std.contains(new Person("小明",2)));
}
}
LinkedList子类:
继承结构以下:基于链表形式的实现
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable
实现LinkedList的集合操做:
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.LinkedList;
import java.util.List;
public class LinkList链表操做 {
public static void main(String[] args) {
List<String> all = new LinkedList<String>();
all.add("java");
all.add("python");
all.add("Linux");
System.out.println(all);
System.out.println(all.get(2));
System.out.println(all.get(1));
}
}
Vector子类:
继承结构以下:
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
从继承结构上能够看出,Vector子类的使用方式与ArrayList的使用方式相同;
package Java从入门到项目实战.Java类集框架.List集合;
import java.util.List;
import java.util.Vector;
public class Vector子类实现List接口 {
public static void main(String[] args) {
List<String> all = new Vector<String>();
all.add("asda");
all.add("你好");
all.add("buhao");
System.out.println(all);
}
}
不一样点:
如下是vector操做方法,采用的方式是synchronized 同步处理;属于线程安全,可是效率没有ArrayList高;
在考虑线程并发访问的状况下才能去使用vector子类。
public synchronized void copyInto(Object[] anArray)
Set集合
主要特色是:内部不容许保存重复元素
继承结构以下:
public interface Set<E> extends Collection<E>
实例化:
package Java从入门到项目实战.Java类集框架.Set集合;
import java.util.Set;
public class set的基本使用 {
public static void main(String[] args) {
//不能有重复值,若是有的话会报错
//Exception in thread "main" java.lang.IllegalArgumentException: duplicate element: 世界
// Set<String> all = Set.of("你好","xbhog","世界","世界");
Set<String> all = Set.of("你好","xbhog","世界");
System.out.println(all);
}
}
HashSet子类:
特色:散列存放且不容许保存重复元素 即:无序存放
继承结构以下:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable
HashSet保存数据:
package Java从入门到项目实战.Java类集框架.Set集合;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSet保存数据 { //数据采用无序的保存方式,且不容许保存重复的数据
public static void main(String[] args) {
//保存的类型是String
Set<String> all = new HashSet<String>();
all.add("小李");
all.add("小红");
all.add("小1");
all.add("小2");
all.add("小花");
all.add("小花");
System.out.println(all);
Iterator<String> iter = all.iterator();
while(iter.hasNext()){
String str = iter.next();
System.out.print(str+"、");
}
}
}
LinkedHashSet子类:JDK1.4加入---解决HashSet没法顺序保存的数据
实现是基于链表保存的数据:增长的顺序就是集合的保存顺序,且不会保存重复的数据。
package Java从入门到项目实战.Java类集框架.Set集合;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;
public class 链表实现LinkHashSet { //基于链表的操做,且保存的数据为顺序保存
public static void main(String[] args) {
Set<String> all = new LinkedHashSet<String>();
all.add("小李老师");
all.add("小bai");
all.add("小明");
all.add("小黄");
System.out.println(all);
Iterator<String> iter = all.iterator();
while (iter.hasNext()) {
String str = iter.next();
System.out.println(str + "、");
}
}
}
TreeSet子类:
特色:使得集合中保存的数据进行有序排列
其继承结构以下:
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable
TreeSet子类继承AbstractSet抽象类并实现了NavigableSet接口(该接口为排序标准接口,是Set的子类)
TreeSet保存数据:
package Java从入门到项目实战.Java类集框架.Set集合;
import java.util.*;
public class TreeSet子类的有序排列 {
//全部保存的数据按照从大到小的顺序(字符按照字母大小顺序依次比较)
public static void main(String[] args) {
Set<String> all = new TreeSet<String>();
all.add("11");
all.add("hello");
all.add("hello");
all.add("world");
all.add("add");
all.add("部署");
all.add("啊哈");
System.out.println(all);
}
}
优先级:数字排序>字母排序>汉字排序
TreeSet子类排序分析:
该类子在进行有序数据存储时依据的是Comparable接口实现排序;须要注意的是在覆写compareTo()方法时须要进行类中所有属性的比较;不然出现部分属性相同时被误判为同一个对象;致使重复元素判断失败;
package Java从入门到项目实战.Java类集框架.Set集合;
import java.util.Set;
import java.util.TreeSet;
class Member implements Comparable<Member>{
private String name;
private int age;
public Member(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+this.name +"、年龄:"+this.age;
}
@Override
public int compareTo(Member per){
if(this.age < per.age) return -1;
else if(this.age > per.age) return 1; //年龄相同时比较名字
else {
return this.name.compareTo(per.name);
}
}
}
public class TreeSet子类排序分析 {
public static void main(String[] args) {
Set<Member> all = new TreeSet<Member>();
all.add(new Member("张三",12));
all.add(new Member("李四",12));
all.add(new Member("王五",20));
all.add(new Member("王五",20));
all.forEach(System.out::println);
}
}
关于compareTo的相关描述,能够到源码下的注释中翻译了解。
重复元素消除:(非排序的集合中的重复元素)
依靠两种方法:
Hash码:public int Hashcode();
对象比较:public boolean equals(Object obj);
在进行对象比较的过程当中,首先会使用hashCode()方法与集合中已经保存的代码进行匹配比较;若是代码相同则再使用equals()方法进行属性的依次比较;若是所有相同;则为相同元素;
package Java从入门到项目实战.Java类集框架.Set集合;
import java.util.*;
class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (age != person.age) return false;
if (name != null ? !name.equals(person.name) : person.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
public class 重复元素消除 {
public static void main(String[] args) {
Set<Person> all = new HashSet<Person>();
all.add(new Person("张三",19));
all.add(new Person("李四",19));
all.add(new Person("王五",20));
all.add(new Person("王五",20));
all.add(new Person("魏六",66));
all.add(new Person("xbhog",10));
System.out.println("------------第一种输入方式-----------");
all.forEach((person -> {
System.out.println(person.getName()+"----"+person.getAge());
}));
System.out.println("------------第二种输入方式-----------");
Iterator<Person> iter = all.iterator();
while(iter.hasNext()){
Person per = iter.next();
System.out.println(per.getName() + " "+per.getAge());
}
}
}
经过hashSet 保存了重复元素,再两个方法的做用实现去重操做。
集合输出
在类框架中的对于集合的标准输出为:Iterator
、ListIterator
、Enumeration
、foreach
;
Iterator迭代输出:
迭代输出:依次判断每一个元素,判断其是否有内容,若是有内容就输出。
Iterator接口依靠Iterable接口中的iterate()方法实例化的;
Iterator经常使用方法:
E |
next() |
返回迭代中的下一个元素。 |
default void |
remove() |
从基础集合中移除该迭代器返回的最后一个元素(可选操做)。 |
boolean |
hasNext() |
若是迭代有更多元素则返回true。 |
实例:
package Java从入门到项目实战.Java类集框架.集合输出;
import java.util.Iterator;
import java.util.Set;
public class Iterator输出Set集合 {
public static void main(String[] args) {
Set<String> all = Set.of("Hello","World","xbhog");
Iterator<String> iter = all.iterator();
while(iter.hasNext()){
String str = iter.next();
System.out.print(str+"、");
}
}
}
关于数据删除的问题:
在Collection中与Iterator都有remove方法;那么应该选择什么呢:
Collection无论三七二十一,就给你删除了,这样会形成Java.util.ConcurrentModificationException错误;
而Iterator在迭代的时候;都会须要依据存储的数据内容进行判断;
因此只有Iterator接口中的remove才是实现删除数据的正确方法。
如:
package cn.mldn.demo;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class JavaCollectDemo {
public static void main(String[] args) {
// 若是使用Set.of()或List.of()建立的集合不支持删除操做
Set<String> all = new HashSet<String>();
all.add("小白"); // 保存数据
all.add("Java"); // 保存数据
all.add("Java"); // 保存重复数据
all.add("xbhog"); // 保存数据
Iterator<String> iter = all.iterator();
while (iter.hasNext()) { // 集合是否有数据
String str = iter.next(); // 获取数据
if ("Java".equals(str)) {
iter.remove() ; // 删除当前数据
} else {
System.out.print(str + "、");
}
}
}
}
ListIterator双向迭代:
首先区别Iterator的做用:
Iterator完成的是从前向后单向输出
ListIterator完成的是从后向前输出
可是只有实现Iterator从前向后的输出后才能实现ListIterator从后向前的输出(注意前后顺序);
由于只有实现从前向后输出结束后,指针才执行最后;
若是顺序相反则会输出为空。
其下的扩充方法:
boolean |
hasPrevious() |
若是该列表迭代器在反向遍历列表时拥有更多元素,则返回true。 |
E |
previous() |
返回列表中的前一个元素,并向后移动光标位置。 |
实例:执行双向迭代
package Java从入门到项目实战.Java类集框架.集合输出;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class 双向迭代输出ListIterator {
public static void main(String[] args) {
List<String> all = new ArrayList<String>();
all.add("小李");
all.add("小宋");
all.add("xbhog");
ListIterator<String> iter = all.listIterator();
System.out.println("执行从后往前的操做的话必须须要先执行从前日后的操做,这样才能是指针指向后面");
//若是不按照相关操做进行,则从后往前的操做输出为空;
System.out.println("从前日后输出:-----------");
while(iter.hasNext()){
System.out.println(iter.next());
}
System.out.println("从后往前输出:------------");
while(iter.hasPrevious()){ //判断是否有前一个元素
System.out.println(iter.previous()); //有的输出前一个元素
}
}
}
ListIterator接口实现了List集合的双向迭代操做。
Enumeration枚举输出:
该类型的输出是创建在Vector集合上的;至关于依附产品;
其接口经常使用方法:
boolean |
hasMoreElements() |
测试此枚举是否包含更多元素。 |
E |
nextElement() |
若是该枚举对象至少还有一个要提供的元素,则返回该枚举的下一个元素。 |
实例:输出vector集合数据
package cn.mldn.demo;
import java.util.Enumeration;
import java.util.Vector;
public class JavaCollectDemo {
public static void main(String[] args) {
Vector<String> all = new Vector<String>(); // 实例化Vector
all.add("小黄"); // 保存数据
all.add("Java"); // 保存数据
all.add("xbhog"); // 保存数据
Enumeration<String> enu = all.elements() ; // 获取Enumeration实例
while (enu.hasMoreElements()) {
String str = enu.nextElement() ;
System.out.print(str + "、");
}
}
}
注意Enumeration只有输出操做没有删除操做。
foreach输出:
没啥好说的,既能够实现数组输出外,也支持集合的输出;
package cn.mldn.demo;
import java.util.HashSet;
import java.util.Set;
public class JavaCollectDemo {
public static void main(String[] args) {
Set<String> all = new HashSet<String>(); // 实例化Set
all.add("小黄"); // 保存数据
all.add("Java"); // 保存数据
all.add("xbhog"); // 保存数据
for (String str : all) {
System.out.print(str + "、");
}
}
}
实现自定义foreach输出:
首先须要知道实现foreach须要Iterator接口的支持;因此在Set与List集合才能够经过foreach实现输出;
若是咱们本身要实现自定义类的输出,那么咱们就须要实例化Iterable接口完成iterator的功能;
package cn.mldn.demo;
import java.util.Iterator;
class Message implements Iterable<String> {// 支持foreach输出
private String[] content = { "Java", "Python", "Ubuntu" }; // 信息内容
private int foot; // 操做脚标
@Override
public Iterator<String> iterator() { // 获取Iterator实例
return new MessageIterator();
}
private class MessageIterator implements Iterator<String> {
@Override
public boolean hasNext() { // 判断是否存在内容
return Message.this.foot <
Message.this.content.length;
}
@Override
public String next() { // 获取数据
return Message.this.content[Message.this.foot++];
}
}
}
public class JavaCollectDemo {
public static void main(String[] args) {
Message message = new Message(); // Iterable接口实例
for (String msg : message) { // foreach输出
System.out.print(msg + "、");
}
}
}
Map集合
map的集合形式是键值对的方式;
其经常使用方法:
V |
get(Object key) |
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. |
V |
put(K key, V value) |
Associates the specified value with the specified key in this map (optional operation). |
static <K,V> Map<K,V> |
of() |
Returns an unmodifiable map containing zero mappings. |
其中Map.of()能够将每一组数据转为map进行保存;
使用Map保存Key-Value数据:
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
public class 保存Key_Value数据 {
public static void main(String[] args) {
// 若是Key重复 则会报错:java.lang.IllegalArgumentException
// 若是Value与Key设置为null,则会报错:java.lang.NullPointerException
Map<String,Integer> map = Map.of("one",1,"two",null);
System.out.println(map);
// System.out.println(map.get("one"));
// Put只能在map子类中使用
}
}
注意点:
若是Key重复 则会报错:java.lang.IllegalArgumentException
若是Value与Key设置为null,则会报错:java.lang.NullPointerException
HashMap子类:
特色:采用散列方式保存数据,即无序排列
继承结构:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
HashMap进行map集合的操做:
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.HashMap;
import java.util.Map;
public class HahMap子类 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String,Integer>();
// 进行Map的集合操做
// map.put("One",1);
// map.put("Two",2);
// map.put("Three",3);
// System.out.println(map);
// Map数据的保存方法:
System.out.println(map.put("One",1)); //保存数据,可是保存的数据的key不存在,返回null
System.out.println(map.put("One",101)); // 返回1,也就是返回的是覆盖掉的值
map.put("Three",3);
map.put("demo1",4);
map.put("demo2",null);
map.put("Te",6);
map.put(null,7);
/*结果
* null、7
* */
System.out.println(map.get("demo2"));
System.out.println(map.get(null));
}
}
注意两个输出的注释:
//Map数据的保存方法:
System.out.println(map.put("One",1)); //保存数据,可是保存的数据的key不存在,返回null
System.out.println(map.put("One",101)); // 返回1,也就是返回的是覆盖掉的值
在使用Map保存数据的时候Key与Value都不能使用null,可是使用HashMap进行保存数据能够将Key或Value设置为null,固然也能够Key=Value=null,可是这样的实现保存毫无心义。
put方法在发生覆盖钱均可以返回原始内容,这样就能够依据返回结果来判断所设置的key是否存在;
HashMap数据扩充操做原理分析:
1) 首先观察构造方法:
设置数据扩充阈值;
public HashMap() {
// all other fields defaulted
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
而后跳转DEFAULT_LOAD_FACTOR
查看:
做用:容量的扩充阈值
/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
经过源码能够发现,每一个Hashmap在对象实例化的时候都已经考虑到了数据存储的扩充问题;
2) 观察HashMap中的put方法
public V put(K key,V value){
return putVal(hash(key),key,value,false,true);
}
在使用put方法进行数据保存的时候会调用putVal方法,同时会将key进行哈希处理(生成hash码)
而putVal()方法为了方便数据保存会将数据封装为一个Node节点类对象,而在使用putVal()方法的操做过程会调用reasize()方法进行扩容;
3)容量扩充
当保存的数据超过既定的存储容量则会进行扩容,原则以下:
常量地址:DEFAULT_INITIAL_CAPACITY
;做为初始化的容量配置,然后1向左移4为-》16;
常量的默认大小为16个元素,也就是说默承认以保存的最大的内容是16;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
当保存的数据内容超过了设置的阈值DEFAULT_LOAD_FACTOR = 0.75f
至关于容量x阈值 = 16*0.75 = 12;即保存到12个元素的时候就会进行容量扩充;
扩充的模式是2倍扩充:即每一次扩充2倍的容量。
4)大数据下的数据存储方式:
在JDK1.8以后来到大数据时代,这就触发了HashMap在大数据量中的访问效率问题;
其中提供了一个重要的常量:TREEIFY_THRESHOLD
static final int TREEIFY_THRESHOLD = 8;
在使用HashMap进行保存的时候,若是保存的数据个数没有超过阈值8,那么会按照链表的形式进行数据的存储;而超过了这个阈值,则会将链表转为红黑树以实现树的平衡;而且利用左旋与右旋保证数据的查询性能。
LinkedHashMap子类:
特色:基于链表形式实现偶对的存储,能够保证存储顺序与数据增长的顺序相同;
继承结构:
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
使用LinkedHashMao子类存储数据:
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMap子类存储数据 {
public static void main(String[] args) {
Map<String,Integer> map = new LinkedHashMap<String,Integer>();
map.put("张三",1);
map.put("李四",2);
map.put("王五",3);
map.put(null,3);
map.put("赵六",null);
System.out.println(map);
}
}
运行能够发现集合的保存的顺序与数据增长顺序相同;同时LinkedHashMap子类容许保存的Key或value内容为null;
Hashtable子类:
其继承结构以下:
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable
使用Hashtable子类保存数据:
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMap子类存储数据 {
public static void main(String[] args) {
Map<String,Integer> map = new Hashtable<String,Integer>();
map.put("张三",1);
map.put("李四",2);
System.out.println(map);
}
}
HashMap与Hashtable的区别:
HashMap中的 方法都是异步操做(非线程安全),HashMap中容许保存null数据
Hashtable中的方法都是同步操做(线程安全),可是效率慢,Hashtable不容许保存Null数据;不然会出现NUllpointException;
TreeMap子类:
特色:TreeMap属于有序的Map集合类型;它能够按照key进行排序;因此须要Comaprable接口配合;
继承结构以下:
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable
TreeMap子类进行数据Key的排序:
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.Map;
import java.util.TreeMap;
public class TreeMap子类进行数据Key的排序 {
public static void main(String[] args) {
// 由于该程序保存的Key属于String类型,因为String中实现了Comparable接口,因此
// 能够根据保存的字符的编码进行由低到高的进行排序
/*
* public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
*
*
* */
Map<String,Integer> map = new TreeMap<String,Integer>();
map.put("C",3);
map.put("B",2);
map.put("A",1);
System.out.println(map);
}
}
Map.Entry内部接口:
在JDK1.9开始能够利用Map接口中建立Map.entry内部接口实例;
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.Map;
public class Map_Entry内部接口 {
public static void main(String[] args) {
Map.Entry<String,Integer> entry = Map.entry("One",1);
System.out.println(entry.getKey());
System.out.println(entry.getValue());
//观察使用的子类
System.out.println(entry.getClass().getName());
}
}
在程序继续宁Map.Entry对象构建的时,只传入Key和Value就会自动利用KeyValueHolder子类实例化Map.Entry接口对象。
Iterator输出Map集合:
集合数据输出的标准形式是基于Iterator接口完成的;Collection接口直接提供iterator方法能够得到iterator接口实例;但因为Map接口中保存的数据是多个Map.Entry接口封装的二元偶对象,因此就必须采用Map集合的迭代输出;
使得Map接口中的entrySet(),将Map集合变为Set集合;
取得Set接口实例后就能够利用iterator方法取得iterator的实例化对象;
使用iterator迭代找到每个Map.Entry对象,并进行Key与Value的分。
Iterator和foreach输出Map集合:
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Map集合的输出问题 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("One",1);
map.put("two",2);
// 输出的map中的Key与Value的值
Set<Map.Entry<String, Integer>> set = map.entrySet();//将Map集合转变为Set集合
Iterator<Map.Entry<String,Integer>> iter = set.iterator(); //获取Iterator接口
while(iter.hasNext()){
// Set中存的都是Map.Entry()对象
Map.Entry<String, Integer> me = iter.next();
System.out.print(me.getKey()+" "+me.getValue());
}
// System.out.println("\n");
//foreach循环输出Map集合:
for(Map.Entry<String,Integer> entry:set){
System.out.print(entry.getKey()+" "+entry.getValue());
}
}
}
自定义Key类型:
采用自定义类的形式实现,可是做为Key类型的类因为存在数据查找的需求,因此必须在类中覆写hashcode()与equals()方法。
package Java从入门到项目实战.Java类集框架.Map集合;
import java.util.HashMap;
import java.util.Map;
class Member{
private String name;
private int age;
public Member(String name,int age){
this.name = name;
this.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 boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Member)) return false;
Member member = (Member) o;
if (age != member.age) return false;
if (name != null ? !name.equals(member.name) : member.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
/*
* Key进行自定义;做为Key类型的类因为存在数据查找的需求,因此应该在类中覆写HashCode() 和equals();
* */
public class 自定义Key的值 {
public static void main(String[] args) {
Map<Member,String> map = new HashMap<Member,String>();
map.put(new Member("张三",22),"xbhog");
map.put(new Member("李四",23),"博客");
map.put(new Member("王五",26),"welcome");
System.out.println(map.get(new Member("张三",22)));
}
}
在存储大量的数据中,key仍是可能出现重复的问题,这个问题叫Hash冲突;
解决的方式:
链地址法(拉链法)、开放寻址、再哈希、创建公共溢出区;
source: https://www.cnblogs.com/xbhog/p/14601323.html

喜欢,在看
本文分享自微信公众号 - JAVA乐园(happyhuangjinjin88)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。