工具类
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( “~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~” );
😊**list****.****remove****(**** ****1**** ****);**** // 删除索引 1 处的元素**<br /> **System**.out.println( list );
😊**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( “岳飞” );
**List**<**String**> list2 = **new** **ArrayList**<**String**>();<br /> list2.add( "文天祥" );<br /> list2.add( "辛弃疾" );
list1.addAll( 3 , list2 ) ; // boolean addAll( int index, Collection<? extends E> c )
**System**.out.println( list1 );
**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 /> }
**System**.out.println( "~ ~ ~ ~ ~ ~" );<br />**//方法二**:<br /> **Iterator**<**String**> itor = list1.iterator();
**while**( itor.hasNext() ) {<br /> **String** x = itor.next();<br /> **System**.out.println( x );<br /> }
**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
**for**( **int** i = 0 , n = list.size() ; i < n ; i++ ) {<br /> **System**.out.println( list.get( i ) );<br /> }
**System**.out.println( "~ ~ ~ ~ ~ ~" );<br />//倒序输出:<br /> **for**( **int** i = list.size() - 1 ; i >= 0 ; i-- ) {<br /> **System**.out.println( list.get( i ) );<br /> }
**System**.out.println( "~ ~ ~ ~ ~ ~" );
**ListIterator**<**String**> listIterator = list.**listIterator**();
**while**( listIterator.hasNext() ) {<br /> **int** index = listIterator.nextIndex() ;<br /> **String** element = listIterator.next();<br /> **System**.out.println( index + " - " + element );<br /> }
**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( “~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~” );
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 ;
**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 );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 从 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方法的作用
**List**<**String**> x = **new** **ArrayList**<**String**>();<br /> x.add( "周勃" );<br /> x.add( "卫青" );<br /> x.add( "霍去病" );<br /> x.add( "岳飞" );<br /> x.add( "文天祥" );<br /> x.add( "辛弃疾" );
**Iterator**<**String**> t = x.iterator(); // 获得一个可以迭代 x 的 迭代器
**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( “辛弃疾” );
**ListIterator**<**String**> t = x.listIterator();
**while**( t.hasNext() ) { // 是否有下一个元素<br /> **String** s = t.next(); // 获取下一个元素<br /> **if**( s.contentEquals( "霍去病" ) ) { // contentEquals 是 String 类中的方法<br /> // 使用参数指定的对象 替换 目前已经获取到的元素<br /> t.set( "霍光" ); // ( 即刚刚调用 next 方法获取到谁就替换谁,集合中的数据会因此而发生改变 )<br /> }<br /> }
**System**.out.println( x );
**while**( t.hasPrevious() ) { // 是否有前一个元素<br /> **String** s = t.previous() ; // 获取前一个元素<br /> **if**( s.contentEquals( "霍光" ) ) {<br /> // 将参数指定的对象 添加到 目前已经获取到的元素 之前 ( List是有顺序存放的 )<br /> t.add( "霍去病" );<br /> }<br /> }
**System**.out.println( x );
// 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
特点
抽象方法
booiean offer(E e)
E peek()
E poll()
boolean add(E e)
E element()
E remove()
Queue<String> queue = new LinkedList<>(); // “菱形语法”
queue.add( "唐三藏" ) ; // 在队列尾部添加元素<br /> queue.add( "孙悟空" ) ;<br /> queue.add( "小白龙" );<br /> queue.add( "猪悟能" );<br /> queue.add( "沙悟净" );
**System**.out.println( queue );
**String** head = queue.element() ; // 获取队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
head = queue.remove(); // 移除队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
queue.clear(); // 因为 Queue 接口继承了 Collection 接口,所以也是 collection<br /> // queue.element() ; // java.lang.NoSuchElementException<br /> // queue.remove(); // java.lang.NoSuchElementException
// 创建一个队列 ( 接口类型的引用变量 指向了 实现类类型的对象 )<br /> **Queue**<**String**> queue = **new** **LinkedList**<>(); // "菱形语法"
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 );
**String** head = queue.peek() ; // 获取队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
head = queue.poll(); // 移除队列头部元素<br /> **System**.out.println( head );<br /> **System**.out.println( queue );
queue.clear(); // 因为 Queue 接口继承了 Collection 接口,所以也是 collection
**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<>();
// 将 deque 所指向的 对象当做一个普通集合来使用<br /> deque.add( "韩信" );<br /> deque.add( "晁错" );<br /> deque.add( "窦婴" );
// 输出 deque 所指向对象的字符串形式<br /> **System**.out.println( deque ); // 通过 字符串 形式 来 区分 哪里是头,哪里是尾
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
/* = = = = 以 "字符串形式" 左侧为头部,以 "字符串形式" 右侧为尾部 = = = = */<br /> deque.offerLast( "李广" ); // 通过 offerLast 方法在队列尾部添加元素<br /> deque.offerLast( "李敢" );<br /> deque.offerLast( "李凌" );
**System**.out.println( deque ); // 再次输出字符串形式
**String** head = deque.peekFirst(); // 通过 peekFirst 方法可以检查队列头部的元素 (但不删除)<br /> **System**.out.println( head );
**System**.out.println( deque );
head = deque.pollFirst(); // 通过 pollFirst 方法可以移除队列头部元素(并返回该元素)<br /> **System**.out.println( head );
**System**.out.println( deque );
deque.clear(); // 清空集合 ( 将双端队列对象 当做集合使用 )<br /> **System**.out.println( deque.peekFirst() ); // null<br /> **System**.out.println( deque.pollFirst() ); // null
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
deque.addLast( "李广" ); // 通过 addLast 方法在队列尾部添加元素<br /> deque.addLast( "李敢" );<br /> deque.addLast( "李凌" );
**System**.out.println( deque );
**System**.out.println( deque.getFirst() );<br /> **System**.out.println( deque.removeFirst() );
**System**.out.println( deque );
deque.clear();
// 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() );
**System**.out.println( d.pollFirst() + " 出队" ); // 出队 : 先进先出 ( FIFO : First In , First Out )<br /> **System**.out.println( "队列: " + d.toString() );
**System**.out.println( d.pollFirst() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
**System**.out.println( d.pollFirst() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 以 "字符串形式" 右侧为头部,以 "字符串形式" 左侧为尾部<br /> d.offerFirst( "李广" );<br /> d.offerFirst( "李敢" );<br /> d.offerFirst( "李凌" );
**System**.out.println( "队列: " + d.toString() );
**System**.out.println( d.pollLast() + " 出队"); // 移除 队列头部 元素<br /> **System**.out.println( "队列: " + d.toString() );
**System**.out.println( d.pollLast() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
**System**.out.println( d.pollLast() + " 出队");<br /> **System**.out.println( "队列: " + d.toString() );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 以 "字符串形式" 右侧为【栈顶】,以 "字符串形式" 左侧为【栈底】 <br /> d.offerLast( "刘彻" ); // 向【栈顶】压入元素<br /> d.offerLast( "刘启" ); // 向【栈顶】压入元素<br /> d.offerLast( "刘恒" ); // 向【栈顶】压入元素<br /> **System**.out.println( d.toString() );
**System**.out.println( d.peekLast() ) ; // 检查栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pollLast() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pollLast() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pollLast() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 以 "字符串形式" 左侧为【栈顶】,以 "字符串形式" 右侧为【栈底】 <br /> d.offerFirst( "乾隆" );<br /> d.offerFirst( "雍正" );<br /> d.offerFirst( "康熙" ); // 向【栈顶】压入元素
**System**.out.println( d );
**System**.out.println( d.peekFirst() ) ; // 检查栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pollFirst() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pollFirst() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pollFirst() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// java.util.Deque 接口中直接定义了 "栈" 操作相关的方法: push( E item ) / peek() / pop()
d.push( "武则天" ); // 将元素压入栈顶<br /> d.push( "李治" );<br /> d.push( "李世民" );<br /> d.push( "李渊" );
**System**.out.println( d );
**System**.out.println( d.peek() ) ; // 检查栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pop() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pop() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
**System**.out.println( d.pop() ) ; // 弹出栈顶元素<br /> **System**.out.println( d );
理解哈希表/桶/‘哈希算法’/操作链表
如果某个数组中的所有元素 都可以 根据同一个的规则计算出其索引,
也就是,
向数组中添加新元素时,可以根据 元素 计算出 该元素 应该放在数组中哪个位置,
则这种数组就是所谓的 “哈希表”
比如:
int value = 7 ;
*int index = value % array.length ; // 通过某种规则可以计算出 某个值 应该存放在数组的哪个位置
array[ index ] = value ;
但是当7和77都传进是7个时就会发生冲突,这时候就引入了“桶”的概念。用链表表示桶。
**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 /> }
@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** {
**Object**[] table = **new** **Object**[ 10 ];<br /> **System**.out.println( **Arrays**.toString( table ) );
add( 77 , table);<br /> **System**.out.println( **Arrays**.toString( table ) );
add( 7 , table );<br /> **System**.out.println( **Arrays**.toString( table ) );
add( 177 , table );<br /> add( 277 , table );<br /> **System**.out.println( **Arrays**.toString( table ) );
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 /> }
**public** **static** **int** **hash**( **int** value , **int** length ) {<br /> // 根据 某个值 和 数组 长度 计算 该值应该在数组的哪个位置存放<br /> **return** value % length ;<br /> }
Map
实现类
Hashmap
Hashtable
不允许键或值为null
Map<String,Integer> map = null ;
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 );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
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克 )
**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 /> }
// 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 /> }
**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 />**比较下面两个对象是否一样,add(a)remove(P) 会不会成功?会的。**<br />**<br />** Panda** p = **new** **Panda**( "团团" , **LocalDate**.of( 2018 , 8 , 10 ) , 15000 );<br /> **Panda** a = **new** **Panda**( "团团" , **LocalDate**.of( 2018 , 8 , 10 ) , 15000 );
**System**.out.println( p == a ); // false<br /> **System**.out.println( p.equals( a ) ); // true<br /> **System**.out.println( p.hashCode() == a.hashCode() ); // true
**Map**<**Panda**,**String**> map = **new** **HashMap**<>();
map.put( p , "团团是只不可爱的熊猫" );
**System**.out.println( map );
**System**.out.println( map.containsKey( p ) ); // true<br /> **System**.out.println( map.containsKey( a ) ); // true
**System**.out.println( map.remove( a ) ) ; // true
**System**.out.println( map );
Set
特点
Hashset
与collection相似,也有add等方法,只不过不能重复
底层其实是map实现的
private static final Object PRESENT = new Object();
private transient HashMap
public EcutSet(){
map=new HashMap<>();
}
//比如这个size方法
@Override
public int size() {
return map.size();
}
TreeTest
有序存放,可排序
Set<String> set = new HashSet<>();
**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 );
**System**.out.println( set );
**System**.out.println( set.add( "张翠山" ) ); // false : map.put( "张翠山" , PRESENT) == null<br /> **System**.out.println( set );
**System**.out.println(set.remove( "张翠山" ) ); // true<br /> **System**.out.println( set );
**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**<>();
ht.put( "藜蒿炒腊肉" , 10 );<br /> ht.put( "蒜苗回锅肉" , 12 );<br /> ht.put( "土豆片回锅肉" , 12 );<br /> ht.put( "毛血旺" , 10 );<br /> ht.put( "蒜苗回锅肉" , 15 );
**System**.out.println( ht );
**Enumeration**<**String**> keys = ht.keys();
**while**( keys.hasMoreElements() ) {<br /> **String** key = **keys****.****nextElement****();**<br /> **System**.out.println( key );<br /> }
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**Enumeration**<**Integer**> values = ht.elements();<br /> **while**( values.hasMoreElements() ) {<br /> **Integer ****value**** ****=**** ****values****.****nextElement****();**<br /> **System**.out.println( value );<br /> }
理解SortMap
特点
子接口 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 );
map.put( 10 , "十" );<br /> **System**.out.println( map );
map.put( 50 , "半百" );<br /> **System**.out.println( map );
map.put( 1000 , "千" );<br /> **System**.out.println( map );
map.put( 0 , "个" );<br /> **System**.out.println( map );
**System**.out.println( map.firstKey() ); // SortedMap 中 firstKey 获取 Map 中第一个 key<br /> **System**.out.println( map.lastKey() ); // SortedMap 中 firstKey 获取 Map 中最后一个 key
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**SortedMap**<**Integer**,**String**> hm = map.headMap( 100 ); // headMap( toKey ) 用于截取 从头开始 到 toKey 前的 "子集"<br /> **System**.out.println( hm );
**SortedMap**<**Integer**,**String**> tm = map.tailMap( 50 ); // tailMap( fromKey ) 用于截取 从 fromKey 开始 到 末尾 的 "子集"<br /> **System**.out.println( tm );
**SortedMap**<**Integer**,**String**> sm = map.subMap( 10 , 100 ); // 截取从 fromKey 到 toKey 之前的 "子集"<br /> **System**.out.println( sm );
测试SortSet
SortedSet<Integer> set = new TreeSet<>();
set.add( 10 );<br /> **System**.out.println( set );
set.add( 7 );<br /> **System**.out.println( set );
set.add( 1 );<br /> **System**.out.println( set );
set.add( 2 );<br /> **System**.out.println( set );
set.add( 5 );<br /> **System**.out.println( set );//[1, 2, 5, 7, 10]
**System**.out.println( set.first() );//1
**System**.out.println( set.last() );//10
**System**.out.println( set.headSet( 5 ) );//[1, 2]
**System**.out.println( set.tailSet( 5 ) );[5, 7, 10]
**System**.out.println( set.subSet( 2 , 7 ) );//[2, 5]<br />若无法自然排序则要用比较器排序(重写equal方法)<br />**TreeMap**<**Monkey**,**String**> ts = **new** **TreeMap**<>();
**Monkey** m = **new** **Monkey**( "孙悟空" , **LocalDate**.of( -400 , 10 , 10 ) );<br /> **System**.out.println( m );<br /> ts.put( m, "斗战胜佛" ); // 如果 m 对应的类型 未实现 Comparable 接口则会抛出 ClassCastException
**Monkey** o = **new** **Monkey**( "六耳猕猴" , **LocalDate**.of( -200 , 9 , 10 ) );<br /> **System**.out.println( o );<br /> ts.put( o , "疑似佛祖派来的卧底" );
**Monkey** n = **new** **Monkey**( "六师傅" , **LocalDate**.of( 1959 , 4 , 12 ) );<br /> **System**.out.println( n );<br /> ts.put( n , "六师傅是个......" );
**System**.out.println( ts );
下面方法让Money自动排序
import java.time.LocalDate;
public class Monkey implements Comparable<Monkey>{
private String name;
private LocalDate** birthdate;
**public** **Monkey**(**String** name, **LocalDate** birthdate) {<br /> **super**();<br /> **this**.name = name;<br /> **this**.birthdate = birthdate;<br /> }
@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 />}