Collection Framework (集合框架).png

工具类

java.util.Arrays
java.util.Collection
java.util.Object

泛型

java.lang.Iterable

java.util.Collection

java.util.List

特点:
有序存放
可重复
可排序
List<String> list = new ArrayList<String>();
list.add( “卫青” );
list.add( “霍去病” );
list.add( “岳飞” );
list.add( “文天祥” );
list.add( “辛弃疾” );
// list 集合中的 元素的存放顺序 与 当时的添加顺序 是相同的
System.out.println( list );
list.add( 2 , “辛弃疾” ); // List 接口重新定义的方法
System.out.println( list );
System.out.println( “~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~” );
List<Integer> numbers = new ArrayList<Integer>();
numbers.add( 100 );
numbers.add( 88 );
numbers.add( 95 );
numbers.add( 6 );
numbers.add( -1 );
numbers.add( 1002 );
numbers.add( 99 );
System.out.println( numbers );
// numbers 中的元素是 Integer ,而 Integer 是实现过 Comparable 接口的 ( 支持自然排序 )
Collections.sort( numbers ); // 使用 java.util.Collections 类的 sort 方法对 List 集合进行排序
System.out.println( numbers ); // 按照 自然顺序 排列
实现类
java.util.ArrayList
特点:内部采用数组存储数据
元素可以为null
不是线程安全的

直接父类:java.util.AbstractList
间接父类:java.util.AbstractCollection

实现接口:java.util.List
java.util.Randomaccess
java.lang.Cloneable
java.io.Serializable

构造:public ArrayList()
public ArratList(Collection<? extends E>c)
public ArrayList(int initialCapacity)

实例方法:
List<String> list = new ArrayList<String>();
list.add( “卫青” );
list.add( “霍去病” );
list.add( “岳飞” );
list.add( “文天祥” );
// list 集合中的 元素的存放顺序 与 当时的添加顺序 是相同的
System.out.println( list );
😊l**ist.add( 2 , “辛弃疾” **); // void add( int index , E element )
System.out.println( list );
System.out.println( “~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~” );

  1. 😊**list****.****remove****(**** ****1**** ****);**** // 删除索引 1 处的元素**<br /> **System**.out.println( list );
  2. 😊**String ****old**** ****=**** ****list****.****set****(**** ****2**** ****,**** ****"霍去病"**** ****)**; // E set( int index , E element ) 设置索引为2的元素为<br />//“霍去病”,并把被替代的元素传给old<br /> **System**.out.println( old );//岳飞<br /> **System**.out.println( list );<br /> 😊**List<String> sub = list.subList( 1 , 3 ) **; // List<E> subList( int from , int to )<br /> **System**.out.println( sub );

迭代List的三种方式
List<String> list1 = new ArrayList<String>();
list1.add( “周勃” );
list1.add( “卫青” );
list1.add( “霍去病” );
list1.add( “岳飞” );

  1. **List**<**String**> list2 = **new** **ArrayList**<**String**>();<br /> list2.add( "文天祥" );<br /> list2.add( "辛弃疾" );
  2. list1.addAll( 3 , list2 ) ; // boolean addAll( int index, Collection<? extends E> c )
  3. **System**.out.println( list1 );
  4. **System**.out.println( "~ ~ ~ ~ ~ ~" );<br /> ** //方法一:**<br />**for**( **int** i = 0 ; i < list1.size() ; i++ ) {<br /> **String** x =** list1.get( i );**<br /> **System**.out.println( x );<br /> }
  5. **System**.out.println( "~ ~ ~ ~ ~ ~" );<br />**//方法二**:<br /> **Iterator**<**String**> itor = list1.iterator();
  6. **while**( itor.hasNext() ) {<br /> **String** x = itor.next();<br /> **System**.out.println( x );<br /> }
  7. **System**.out.println( "~ ~ ~ ~ ~ ~" );<br />**//方法三**<br /> **for**( **String** x : list1 ) {<br /> **System**.out.println( x );<br /> }

List接口的of方法/使用ListIterator来迭代List集合
// 从 Java 9 开始 List 接口中声明了一批 of 方法,用于返回 【定长】的 List 集合
List<String> list = List.of( “韩信” , “晁错” , “窦婴” , “李广” , “李敢” , “李凌” );
System.out.println( list );
// list.add( “李敢” ); // java.lang.UnsupportedOperationException

  1. **for**( **int** i = 0 , n = list.size() ; i < n ; i++ ) {<br /> **System**.out.println( list.get( i ) );<br /> }
  2. **System**.out.println( "~ ~ ~ ~ ~ ~" );<br />//倒序输出:<br /> **for**( **int** i = list.size() - 1 ; i >= 0 ; i-- ) {<br /> **System**.out.println( list.get( i ) );<br /> }
  3. **System**.out.println( "~ ~ ~ ~ ~ ~" );
  4. **ListIterator**<**String**> listIterator = list.**listIterator**();
  5. **while**( listIterator.hasNext() ) {<br /> **int** index = listIterator.nextIndex() ;<br /> **String** element = listIterator.next();<br /> **System**.out.println( index + " - " + element );<br /> }
  6. **System**.out.println( "~ ~ ~ ~ ~ ~" );<br />//用迭代器倒叙输出:<br /> **while**( listIterator.hasPrevious() ) {<br /> **int** index = listIterator.previousIndex() ;<br /> **String** element = listIterator.previous();<br /> **System**.out.println( index + " - " + element );<br /> }

理解不可变的List和定长的List
1、不可变的 List ( Immutable List ) 不支持任何修改操作
List.of 方法返回的 List 实例都是 不可变的
2、java.util.Arrays 类中的 asList( T… a ) 返回的 List 实例是 Arrays 类的 内部类类型 ( ArrayList ),
这种集合支持 set( index , element) 操作 和 排序操作 ,不支持 remove 操作和 add 操作,
同时其长度是固定的 ( 有人称作 定长List )。
3、ArrayList 类的实例 支持 修改操作( add / remove / set ) 、支持 迭代操作 、支持排序
List<String> list = null ;
Class<?> c = null ;
// 从 Java 9 开始 List 接口中声明了一批 of 方法,用于返回 【不可变的 List 实例】
list = List.of( “韩信” , “晁错” , “窦婴” , “李广” , “李敢” , “李凌” );//不可变
System.out.println( list );
c = list.getClass();
System.out.println( c.getName() ); // java.util.ImmutableCollections$ListN
// 尝试修改一个不可变的 List 实例会抛出 UnsupportedOperationException
// list.add( “李敢” ); // java.lang.UnsupportedOperationException
// list.remove(1); // UnsupportedOperationException
// list.clear(); // UnsupportedOperationException
// list.set( 3 , “李将军” ); // UnsupportedOperationException
// Collections.sort( list ); // UnsupportedOperationException

*System
.out.println( “~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~” );

  1. list = **Arrays**.asList("李广" , "李敢" , "李凌" );//定长<br /> **System**.out.println( list );<br /> c = list.getClass();<br /> **System**.out.println( c.getName() ); // java.util.Arrays$ArrayList<br /> // list.add( "李敢" ); // UnsupportedOperationException<br /> // list.remove(1); // UnsupportedOperationException<br /> // list.clear(); // UnsupportedOperationException<br /> list.set( 0 , "李将军" ); // 支持替换操作<br /> **System**.out.println( list );<br /> **Collections**.sort( list );<br /> **System**.out.println( list );

将 数组 转换为 List 集合
1、将 数组 转换为 List 集合
1>、使用 Arrays.asList( T… elements ) 实现 [ 在 Java 9 之前 ]
2>、使用 List.of( E… elements) 实现 [ 从 Java 9 开始 ]
2、为了支持 添加、删除、替换、排序 等操作,
需要重新创建 java.util.ArrayList 实例,
* 并将 Arrays.asList 或 List.of 转换后的 List 实例中的所有元素包含进来

List<Integer> list = null ;

  1. **final** **Integer**[] array = { 99 , 100 , 5 , 200 , 10 , 300 , 86 }; // auto-boxing<br /> // 在 Java 9 之前是使用 Arrays.asList( T... elements ) 方法实现<br /> **List**<**Integer**> alist = **Arrays**.asList( array ); // 将数组转换为一个 定长的List实例<br />// ( java.util.Arrays$ArrayList 类型)<br /> **System**.out.println( alist );<br /> // array[ 0 ] = 199 ; <br /> // System.out.println( alist );<br /> // 根据 数组转换后的 List 重新创建一个 ArrayList 实例,该实例包含了 数组对应的 List 中所有元素<br /> list = **new** **ArrayList**<**Integer**>( alist ); // ArrayList( Collection<? extends E> c )<br /> **System**.out.println( list );<br /> list.add( 9527 );<br /> **System**.out.println( list );
  2. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  3. // 从 Java 9 开始可以使用 List.of( E... elements ) 方法实现<br /> **List**<**Integer**> immutableList = **List**.of( array );<br /> **System**.out.println( immutableList );<br /> list = **new** **ArrayList**<**Integer**>( immutableList );<br /> **System**.out.println( list );<br /> list.add( 8526 );<br /> **System**.out.println( list );

测试java.util.Iterator中的方法并理解remove方法的作用

  1. **List**<**String**> x = **new** **ArrayList**<**String**>();<br /> x.add( "周勃" );<br /> x.add( "卫青" );<br /> x.add( "霍去病" );<br /> x.add( "岳飞" );<br /> x.add( "文天祥" );<br /> x.add( "辛弃疾" );
  2. **Iterator**<**String**> t = x.iterator(); // 获得一个可以迭代 x 的 迭代器
  3. **while**( t.hasNext() ) { // 判断是否存在下一个元素<br /> **String** s = t.next(); // 获取下一个元素<br /> // 判断目前已经获取到的元素是否是 "霍去病"<br /> **if**( s.equals( "霍去病" ) ) {<br /> // x.remove( "霍去病" ); // [ 快速失败 ] JVM 会尽可能抛出 java.util.ConcurrentModificationException <br /> // 当使用 迭代器 或 "for-each loop" 语句 迭代集合时,<br /> // **如果需要删除集合中的元素,应该使用 迭代器的 remove 方法,而不是集合本身的方法 ( 比如 x.remove( "霍去病" ) )**<br /> t.remove(); // 删除目前已经获取到的元素 ( 即刚刚调用 next 方法获取到谁就删除谁 )<br /> }<br /> }

测试ListIterator接口中的方法

1、java.util.ListIterator 接口是 java.util.Iterator 接口的子接口
2、ListIterator 接口中的抽象方法:
boolean hasNext() ;
E next();
int nextIndex();
void remove();
void set( E e );
void add( E e );
int previousIndex();
E previous();
* boolean hasPrevious();

List<String> x = new ArrayList<String>();
x.add( “周勃” );
x.add( “卫青” );
x.add( “霍去病” );
x.add( “岳飞” );
x.add( “文天祥” );
x.add( “辛弃疾” );

  1. **ListIterator**<**String**> t = x.listIterator();
  2. **while**( t.hasNext() ) { // 是否有下一个元素<br /> **String** s = t.next(); // 获取下一个元素<br /> **if**( s.contentEquals( "霍去病" ) ) { // contentEquals 是 String 类中的方法<br /> // 使用参数指定的对象 替换 目前已经获取到的元素<br /> t.set( "霍光" ); // ( 即刚刚调用 next 方法获取到谁就替换谁,集合中的数据会因此而发生改变 )<br /> }<br /> }
  3. **System**.out.println( x );
  4. **while**( t.hasPrevious() ) { // 是否有前一个元素<br /> **String** s = t.previous() ; // 获取前一个元素<br /> **if**( s.contentEquals( "霍光" ) ) {<br /> // 将参数指定的对象 添加到 目前已经获取到的元素 之前 ( List是有顺序存放的 )<br /> t.add( "霍去病" );<br /> }<br /> }
  5. **System**.out.println( x );
  6. // List 接口中提供的 listIterator( int beginIndex ) 方法用于获取可以迭代 beginIndex 及之后的元素的迭代器<br /> **ListIterator**<**String**> itor = x.listIterator( 4 ); // 获取新的迭代器对象,用于迭代 索引 4 及其之后的元素<br /> **while**( itor.hasNext() ) {<br /> **System**.out.println( itor.next() );<br /> }

Java.lang.queue

特点

Queue表示队列
队列的特点是先进先出

抽象方法

booiean offer(E e)
E peek()
E poll()
boolean add(E e)
E element()
E remove()

Queue<String> queue = new LinkedList<>(); // “菱形语法”

  1. queue.add( "唐三藏" ) ; // 在队列尾部添加元素<br /> queue.add( "孙悟空" ) ;<br /> queue.add( "小白龙" );<br /> queue.add( "猪悟能" );<br /> queue.add( "沙悟净" );
  2. **System**.out.println( queue );
  3. **String** head = queue.element() ; // 获取队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
  4. head = queue.remove(); // 移除队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
  5. queue.clear(); // 因为 Queue 接口继承了 Collection 接口,所以也是 collection<br /> // queue.element() ; // java.lang.NoSuchElementException<br /> // queue.remove(); // java.lang.NoSuchElementException
  6. // 创建一个队列 ( 接口类型的引用变量 指向了 实现类类型的对象 )<br /> **Queue**<**String**> queue = **new** **LinkedList**<>(); // "菱形语法"
  7. queue.offer( "唐三藏" ) ; // 在队列尾部添加元素<br /> queue.offer( "孙悟空" ) ;<br /> **System**.out.println( "queue => " + queue );<br /> queue.offer( "小白龙" );<br /> queue.offer( "猪悟能" );<br /> **System**.out.println( "queue => " + queue );<br /> queue.offer( "沙悟净" );<br /> **System**.out.println( "queue => " + queue );
  8. **String** head = queue.peek() ; // 获取队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
  9. head = queue.poll(); // 移除队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
  10. queue.clear(); // 因为 Queue 接口继承了 Collection 接口,所以也是 collection
  11. **System**.out.println( queue.peek() ) ; // null<br /> **System**.out.println( queue.poll() ) ; // null

子接口

java.util.Deque

特点: Deque表示双端队列(double ended queue)
实现类:java.util.LinkdList
抽象方法
boolean offerLast(E e)
E peekFirst()
E pollFirst()
void addLast(E e)
E getFirst()
E removeFirst()
boolean offerFirst(E e)
E peekLast()
E pollLast()
void addFirst(E e)
E getLast()
E removeLast()
void push(E e)
E peek()
E pop()

Deque<String> deque = new LinkedList<>();

  1. // 将 deque 所指向的 对象当做一个普通集合来使用<br /> deque.add( "韩信" );<br /> deque.add( "晁错" );<br /> deque.add( "窦婴" );
  2. // 输出 deque 所指向对象的字符串形式<br /> **System**.out.println( deque ); // 通过 字符串 形式 来 区分 哪里是头,哪里是尾
  3. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  4. /* = = = = 以 "字符串形式" 左侧为头部,以 "字符串形式" 右侧为尾部 = = = = */<br /> deque.offerLast( "李广" ); // 通过 offerLast 方法在队列尾部添加元素<br /> deque.offerLast( "李敢" );<br /> deque.offerLast( "李凌" );
  5. **System**.out.println( deque ); // 再次输出字符串形式
  6. **String** head = deque.peekFirst(); // 通过 peekFirst 方法可以检查队列头部的元素 (但不删除)<br /> **System**.out.println( head );
  7. **System**.out.println( deque );
  8. head = deque.pollFirst(); // 通过 pollFirst 方法可以移除队列头部元素(并返回该元素)<br /> **System**.out.println( head );
  9. **System**.out.println( deque );
  10. deque.clear(); // 清空集合 ( 将双端队列对象 当做集合使用 )<br /> **System**.out.println( deque.peekFirst() ); // null<br /> **System**.out.println( deque.pollFirst() ); // null
  11. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  12. deque.addLast( "李广" ); // 通过 addLast 方法在队列尾部添加元素<br /> deque.addLast( "李敢" );<br /> deque.addLast( "李凌" );
  13. **System**.out.println( deque );
  14. **System**.out.println( deque.getFirst() );<br /> **System**.out.println( deque.removeFirst() );
  15. **System**.out.println( deque );
  16. deque.clear();
  17. // System.out.println( deque.getFirst() ); // NoSuchElementException<br /> // System.out.println( deque.removeFirst() ); // NoSuchElementException


[
将java.util.Deque当做【栈】来使用](https://gitee.com/mozicoding/java-beginner/commit/d295ae89e13655c937fa0a1042d84e66137b7b6b)
Deque<String> d = new LinkedList<>();
// 以 “字符串形式” 左侧为头部,以 “字符串形式” 右侧为尾部
d.offerLast( “韩信” ); // 在队列尾部添加元素
d.offer( “晁错” ); // 与 offerLast 等效
d.offerLast( “窦婴” );
System**.out.println( d.toString() );

  1. **System**.out.println( d.pollFirst() + " 出队" ); // 出队 : 先进先出 ( FIFO : First In , First Out )<br /> **System**.out.println( "队列: " + d.toString() );
  2. **System**.out.println( d.pollFirst() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
  3. **System**.out.println( d.pollFirst() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
  4. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  5. // 以 "字符串形式" 右侧为头部,以 "字符串形式" 左侧为尾部<br /> d.offerFirst( "李广" );<br /> d.offerFirst( "李敢" );<br /> d.offerFirst( "李凌" );
  6. **System**.out.println( "队列: " + d.toString() );
  7. **System**.out.println( d.pollLast() + " 出队"); // 移除 队列头部 元素<br /> **System**.out.println( "队列: " + d.toString() );
  8. **System**.out.println( d.pollLast() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
  9. **System**.out.println( d.pollLast() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
  10. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  11. // 以 "字符串形式" 右侧为【栈顶】,以 "字符串形式" 左侧为【栈底】 <br /> d.offerLast( "刘彻" ); // 向【栈顶】压入元素<br /> d.offerLast( "刘启" ); // 向【栈顶】压入元素<br /> d.offerLast( "刘恒" ); // 向【栈顶】压入元素<br /> **System**.out.println( d.toString() );
  12. **System**.out.println( d.peekLast() ) ; // 检查栈顶元素<br /> **System**.out.println( d );
  13. **System**.out.println( d.pollLast() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  14. **System**.out.println( d.pollLast() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  15. **System**.out.println( d.pollLast() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  16. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  17. // 以 "字符串形式" 左侧为【栈顶】,以 "字符串形式" 右侧为【栈底】 <br /> d.offerFirst( "乾隆" );<br /> d.offerFirst( "雍正" );<br /> d.offerFirst( "康熙" ); // 向【栈顶】压入元素
  18. **System**.out.println( d );
  19. **System**.out.println( d.peekFirst() ) ; // 检查栈顶元素<br /> **System**.out.println( d );
  20. **System**.out.println( d.pollFirst() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  21. **System**.out.println( d.pollFirst() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  22. **System**.out.println( d.pollFirst() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  23. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  24. // java.util.Deque 接口中直接定义了 "栈" 操作相关的方法: push( E item ) / peek() / pop()
  25. d.push( "武则天" ); // 将元素压入栈顶<br /> d.push( "李治" );<br /> d.push( "李世民" );<br /> d.push( "李渊" );
  26. **System**.out.println( d );
  27. **System**.out.println( d.peek() ) ; // 检查栈顶元素<br /> **System**.out.println( d );
  28. **System**.out.println( d.pop() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  29. **System**.out.println( d.pop() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
  30. **System**.out.println( d.pop() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );

理解哈希表/桶/‘哈希算法’/操作链表

如果某个数组中的所有元素 都可以 根据同一个的规则计算出其索引,
也就是,
向数组中添加新元素时,可以根据 元素 计算出 该元素 应该放在数组中哪个位置,
则这种数组就是所谓的 “哈希表”
比如:
int value = 7 ;
*int
index = value % array.length ; // 通过某种规则可以计算出 某个值 应该存放在数组的哪个位置
array[ index ] = value ;

但是当7和77都传进是7个时就会发生冲突,这时候就引入了“桶”的概念。用链表表示桶。

  1. **private** **static** **class** **Node** {<br /> **Object** item ; // 存储数据的实例变量<br /> **Node** next ;<br /> **public** **Node**( **Object** item , **Node** next ) {<br /> **super**();<br /> **this**.item = item;<br /> **this**.next = next;<br /> }
  2. @Override<br /> **public** **String** **toString**() {<br /> **StringBuilder** builder = **new** **StringBuilder**();<br /> builder.append( **String**.valueOf( item ) ) ;<br /> **if**( next != **null** ) {<br /> builder.append( "|" );<br /> builder.append( next.toString() ) ;<br /> }<br /> **return** builder.toString() ;<br /> }<br /> }<br /> **public** **static** **void** **main**(**String**[] args) **throws** **InterruptedException** {
  3. **Object**[] table = **new** **Object**[ 10 ];<br /> **System**.out.println( **Arrays**.toString( table ) );
  4. add( 77 , table);<br /> **System**.out.println( **Arrays**.toString( table ) );
  5. add( 7 , table );<br /> **System**.out.println( **Arrays**.toString( table ) );
  6. add( 177 , table );<br /> add( 277 , table );<br /> **System**.out.println( **Arrays**.toString( table ) );
  7. add( 22 , table );<br /> **System**.out.println( **Arrays**.toString( table ) );<br /> }<br /> **public** **static** **void** **add**( **int** value , **Object**[] table) {<br /> **int** index = hash( value , table.length );<br /> **if**( table[ index ] == **null** ) { //如果 index 处不存在元素 ( 假设 null 就表示不存在元素 )<br /> // 就将 参数传入的值 直接放入该位置<br /> table[ index ] = value ; // auto-boxing<br /> } **else** { // 如果 index 处已经存在数据<br /> **Object** o = table[ index ] ; // 获取 在 index 处所存放的数据<br /> **if**( o **instanceof** **Node** ) { // 按照链表方式处理 ( 遍历链表,找最后一个,把 新的 Node 添加到末尾 )<br /> **Node** node = (**Node**) o ;<br /> **while**( node.next != **null** ) {<br /> node = node.next ;<br /> }<br /> **Node** newNode = **new** **Node**( value , **null** ); // 创建新节点<br /> node.next = newNode ; // 让曾经的最后一个节点指向 新的节点<br /> } **else** {<br /> // 根据 参数传入的值 构造一个新的 Node 对象<br /> **Node** newNode = **new** **Node**( value , **null** ); // 第二个参数使用 null 表示它是最后一个<br /> // 根据 index 处已经存在的元素 创建第一个节点<br /> **Node** firstNode = **new** **Node**( o , newNode ); // 第一个节点指向 新数据 对应的节点<br /> // 将第一个节点添加到 index 处<br /> table[ index ] = firstNode ;<br /> }<br /> }<br /> }
  8. **public** **static** **int** **hash**( **int** value , **int** length ) {<br /> // 根据 某个值 和 数组 长度 计算 该值应该在数组的哪个位置存放<br /> **return** value % length ;<br /> }

Map

实现类

Hashmap

允许键或者值为null

Hashtable

不允许键或值为null
Map<String,Integer> map = null ;

  1. map = **new** **HashMap**<**String**, **Integer**>(); // 在 Java 7 开始允许写作 new HashMap<>()<br /> map.put( "xyz" , 20 );<br /> map.put( **null** , 100 );<br /> map.put( "hello" , **null** );<br /> **System**.out.println( map );
  2. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  3. map = **new** **Hashtable**<>(); // 在 Java 7 之前需要写作 new Hashtable<String, Integer>()<br /> map.put( "xyz" , 20 );<br /> // map.put( null , 100 ); // NullPointerException<br /> // map.put( "hello" , null ); // NullPointerException<br /> map.put( "abs" , 100 );<br /> map.put( "min" , 0 );<br /> **System**.out.println( map );

Hashmap中的put/remove/contain是基于key的equal方法的

//在Panda中重写hash/equal方法
private String name ;
private LocalDate birthdate ;
private int weight ; // 体重 ( 以克为单位 , 1斤 = 500克 )

  1. **public** **Panda**(**String** name, **LocalDate** birthdate, **int** weight) {<br /> **super**();<br /> **this**.name = name;<br /> **this**.birthdate = birthdate;<br /> **this**.weight = weight;<br /> }<br /> @Override<br /> **public** **int** **hashCode**() {<br /> /*<br /> final int prime = 31; // 为什么是 31 ?<br /> int result = 1;<br /> result = prime * result + ((birthdate == null) ? 0 : birthdate.hashCode());<br /> result = prime * result + ((name == null) ? 0 : name.hashCode());<br /> result = prime * result + weight;<br /> return result;<br /> */<br /> **return** **Objects**.hash( birthdate , name , weight );<br /> }<br /> @Override<br /> **public** **boolean** **equals**(**Object** o ) {<br /> **if**( **this** == o ) {<br /> **return** **true** ;<br /> }
  2. // null instanceof 任意类型 都返回 false<br /> **if**( o **instanceof** **Panda** ) { // 参数传入的 o 可能是 Panda 的子类类型的实例<br /> // 判断两者是否是同一个类的实例<br /> **if**( **this**.getClass() == o.getClass() ) {<br /> **Panda** p = ( **Panda** ) o ;<br /> **return** name.equals( p.name ) && birthdate.equals( p.birthdate ) && weight == p.weight ;<br /> }<br /> }
  3. **return** **false** ;<br /> }<br /> @Override<br /> **public** **String** **toString**() {<br /> **return** "( name=" + name + ", birthdate=" + birthdate + ", weight=" + weight + " )";<br /> }<br /> **public** **String** **getName**() {<br /> **return** name;<br /> }<br /> **public** **LocalDate** **getBirthdate**() {<br /> **return** birthdate;<br /> }<br /> **public** **int** **getWeight**() {<br /> **return** weight;<br /> }<br /> **public** **void** **setName**(**String** name) {<br /> **this**.name = name;<br /> }<br /> **public** **void** **setBirthdate**(**LocalDate** birthdate) {<br /> **this**.birthdate = birthdate;<br /> }<br /> **public** **void** **setWeight**(**int** weight) {<br /> **this**.weight = weight;<br /> }<br />**<br />**<br />**<br />**比较下面两个对象是否一样,addaremove(P) 会不会成功?会的。**<br />**<br />** Panda** p = **new** **Panda**( "团团" , **LocalDate**.of( 2018 , 8 , 10 ) , 15000 );<br /> **Panda** a = **new** **Panda**( "团团" , **LocalDate**.of( 2018 , 8 , 10 ) , 15000 );
  4. **System**.out.println( p == a ); // false<br /> **System**.out.println( p.equals( a ) ); // true<br /> **System**.out.println( p.hashCode() == a.hashCode() ); // true
  5. **Map**<**Panda**,**String**> map = **new** **HashMap**<>();
  6. map.put( p , "团团是只不可爱的熊猫" );
  7. **System**.out.println( map );
  8. **System**.out.println( map.containsKey( p ) ); // true<br /> **System**.out.println( map.containsKey( a ) ); // true
  9. **System**.out.println( map.remove( a ) ) ; // true
  10. **System**.out.println( map );

Set

特点

不可以重复
最多包含一个null

Hashset

与collection相似,也有add等方法,只不过不能重复
底层其实是map实现的
private static final Object PRESENT = new Object();
private transient HashMap map;
public EcutSet(){
map=new HashMap<>();
}
//比如这个size方法
@Override
public int size() {
return map.size();
}

TreeTest

有序存放,可排序

Set<String> set = new HashSet<>();

  1. **System**.out.println( set.add( "张三丰" ) ); // map.put( "张三丰" , PRESENT );<br /> **System**.out.println( set.add( "张君宝" ) ); // map.put( "张君宝" , PRESENT );<br /> **System**.out.println( set.add( "张翠山" ) ); // map.put( "张翠山" , PRESENT );
  2. **System**.out.println( set );
  3. **System**.out.println( set.add( "张翠山" ) ); // false : map.put( "张翠山" , PRESENT) == null<br /> **System**.out.println( set );
  4. **System**.out.println(set.remove( "张翠山" ) ); // true<br /> **System**.out.println( set );
  5. **System**.out.println( set.remove( "殷素素" ) ); // false<br /> **System**.out.println( set );

通过Hashtable来测试java.util.Enumeration接口

1、建议使用 Iterator 而不是 Enumeration
2、Enumeration 接口中只有两个方法: hasMoreElements() 、nextElement()
3、Hashtable 类的 keys() 方法返回用于 迭代所有 映射项 的 key 的 Enumeration 对象
4、Hashtable 类的 elements() 方法返回用于 迭代所有 映射项 的 value 的 Enumeration 对象
/

Hashtable<String, Integer> ht = new Hashtable**<>();

  1. ht.put( "藜蒿炒腊肉" , 10 );<br /> ht.put( "蒜苗回锅肉" , 12 );<br /> ht.put( "土豆片回锅肉" , 12 );<br /> ht.put( "毛血旺" , 10 );<br /> ht.put( "蒜苗回锅肉" , 15 );
  2. **System**.out.println( ht );
  3. **Enumeration**<**String**> keys = ht.keys();
  4. **while**( keys.hasMoreElements() ) {<br /> **String** key = **keys****.****nextElement****();**<br /> **System**.out.println( key );<br /> }
  5. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  6. **Enumeration**<**Integer**> values = ht.elements();<br /> **while**( values.hasMoreElements() ) {<br /> **Integer ****value**** ****=**** ****values****.****nextElement****();**<br /> **System**.out.println( value );<br /> }

理解SortMap

特点

根据map集合中的键来排序
可排序
自然排序
比较器排序

子接口 java.util.NavigableMap

提供了针对给定搜索目标返回最接近匹配项的导航方法

实现类 java.util.TreeMap

特点:内部基于红黑数存储映射项
不允许存在键(key)为null的映射项
支持排序:
自然排序
选择器排序
不是线程安全的

构造方法

public TreeMap(Map<?extends k,?extends V> m)
public TreeMap(SortMap<?extends k,?extends V> m)
public TreeMap(Comparator<?super k,?>comparator)

测试SortMap

SortedMap<Integer,String> map = new TreeMap<>();
System.out.println( map );
map.put( 100 , “百” );
System.out.println( map );

  1. map.put( 10 , "十" );<br /> **System**.out.println( map );
  2. map.put( 50 , "半百" );<br /> **System**.out.println( map );
  3. map.put( 1000 , "千" );<br /> **System**.out.println( map );
  4. map.put( 0 , "个" );<br /> **System**.out.println( map );
  5. **System**.out.println( map.firstKey() ); // SortedMap 中 firstKey 获取 Map 中第一个 key<br /> **System**.out.println( map.lastKey() ); // SortedMap 中 firstKey 获取 Map 中最后一个 key
  6. **System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
  7. **SortedMap**<**Integer**,**String**> hm = map.headMap( 100 ); // headMap( toKey ) 用于截取 从头开始 到 toKey 前的 "子集"<br /> **System**.out.println( hm );
  8. **SortedMap**<**Integer**,**String**> tm = map.tailMap( 50 ); // tailMap( fromKey ) 用于截取 从 fromKey 开始 到 末尾 的 "子集"<br /> **System**.out.println( tm );
  9. **SortedMap**<**Integer**,**String**> sm = map.subMap( 10 , 100 ); // 截取从 fromKey 到 toKey 之前的 "子集"<br /> **System**.out.println( sm );

测试SortSet

SortedSet<Integer> set = new TreeSet<>();

  1. set.add( 10 );<br /> **System**.out.println( set );
  2. set.add( 7 );<br /> **System**.out.println( set );
  3. set.add( 1 );<br /> **System**.out.println( set );
  4. set.add( 2 );<br /> **System**.out.println( set );
  5. set.add( 5 );<br /> **System**.out.println( set );//[1, 2, 5, 7, 10]
  6. **System**.out.println( set.first() );//1
  7. **System**.out.println( set.last() );//10
  8. **System**.out.println( set.headSet( 5 ) );//[1, 2]
  9. **System**.out.println( set.tailSet( 5 ) );[5, 7, 10]
  10. **System**.out.println( set.subSet( 2 , 7 ) );//[2, 5]<br />若无法自然排序则要用比较器排序(重写equal方法)<br />**TreeMap**<**Monkey**,**String**> ts = **new** **TreeMap**<>();
  11. **Monkey** m = **new** **Monkey**( "孙悟空" , **LocalDate**.of( -400 , 10 , 10 ) );<br /> **System**.out.println( m );<br /> ts.put( m, "斗战胜佛" ); // 如果 m 对应的类型 未实现 Comparable 接口则会抛出 ClassCastException
  12. **Monkey** o = **new** **Monkey**( "六耳猕猴" , **LocalDate**.of( -200 , 9 , 10 ) );<br /> **System**.out.println( o );<br /> ts.put( o , "疑似佛祖派来的卧底" );
  13. **Monkey** n = **new** **Monkey**( "六师傅" , **LocalDate**.of( 1959 , 4 , 12 ) );<br /> **System**.out.println( n );<br /> ts.put( n , "六师傅是个......" );
  14. **System**.out.println( ts );

下面方法让Money自动排序
import java.time.LocalDate;
public class Monkey implements Comparable<Monkey>{
private String name;
private LocalDate** birthdate;

  1. **public** **Monkey**(**String** name, **LocalDate** birthdate) {<br /> **super**();<br /> **this**.name = name;<br /> **this**.birthdate = birthdate;<br /> }
  2. @Override<br /> **public** **int** **compareTo**( **Monkey** o ) {<br /> **if**( o != **null** ) {<br /> // 借助于 LocalDate 类的 compareTo 方法实现比较<br /> **return** birthdate.compareTo( o.birthdate) ;<br /> }<br /> **return** 0;<br /> }<br /> @Override<br /> **public** **String** **toString**() {<br /> **return** "( name='" + name + "' , birthdate='" + birthdate + "' )";<br /> }<br /> **public** **String** **getName**() {<br /> **return** name;<br /> }<br /> **public** **LocalDate** **getBirthdate**() {<br /> **return** birthdate;<br /> }<br /> **public** **void** **setName**(**String** name) {<br /> **this**.name = name;<br /> }<br /> **public** **void** **setBirthdate**(**LocalDate** birthdate) {<br /> **this**.birthdate = birthdate;<br /> }<br />}