【07-Java 集合】
|
Java集合
集合概述
•为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组)。Java提供集合 类,集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。所有集合类都位于java.util包 下。
•Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的 根接口,这两个接口又包含了一些子接口或实现类。
Collection集合
Map集合
Collection接口
•Collection接口是List、Set和Queue接口的父接口,该接口里定义的方法既可用于操作Set集合,也 可用于操作List和Queue集合。
•Collection提供了大量添加、删除、访问的方法来访问集合元素。 Iterator接口
•Iterator接口也是Java集合框架的成员,但它与Collection系列、Map系列的集合不一样: Collection系列集合、Map系列集合主要用于盛装其他对象,而Iterator则主要用于遍历(即迭代访 问)Collection集合中的元素,Iterator对象也被称为迭代器。
•Iterator接口里定义了如下4个方法: –boolean hasNext():如果被迭代的集合元素没有被遍历,则返回true。 –Object next():返回集合里下一个元素。 –void remove() :删除集合里上一次next方法返回的元素 –void forEachRemaining(Consumer action),这是Java 8为Iterator新增的默认方法,该 方法可使用Lambda表达式来遍历集合元素。
foreach循环遍历集合元素
•使用JDK1.5提供的foreach循环来迭代访问集合元素更加便捷。
•当使用foreach循环迭代访问集合元素时,该集合也不能被改变,否则将引发 ConcurrentModificationException异常。
使用Predicate操作集合
•Java 8为Collection集合新增了一些需要Predicate参数的方法,这些方法可以对集合元素进行过 滤。程序可使用Lambda表达式构建Predicate对象。
Java 8新增的Stream操作
•Java 8还新增了Stream、IntStream、LongStream、DoubleStream等流式API。 •独立使用Stream的步骤如下: –(1)使用Stream或XxxStream的builder()类方法创建该Stream对应Builder。 –(2)重复调用Builder的add()方法向该流中添加多个元素。 –(3)调用Builder的build()方法获取对应的Stream。 –(4)调用Stream的聚集方法。 •Collection接口提供了一个stream()默认方法,该方法可返回该集合对应的流,接下来即可通过流 API来操作集合元素。由于Stream可以对集合元素进行整体的聚集操作,因此Stream极大了丰富了集 合的功能。
本文原创作者:pipi-changing 本文原创出处:http://www.cnblogs.com/pipi-changing/
HashSet类
•HashSet是Set接口的典型实现,大多时候使用Set集合时就是使用这个实现类。HashSet按Hash算 法来存储集合中的元素,因此具有很好的存取和查找性能。
•当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的 hashCode值,然后根据该HashCode值来决定该对象在HashSet中存储位置。如果有两个元素通过 equals方法比较返回true,但它们的hashCode()方法返回值不相等,HashSet将会把它们存储在不 同位置,也就可以添加成功。
HashSet的特征
•不能保证元素的排列顺序,顺序可能与元素的添加顺序不同,元素的顺序可能变化。
•HashSet不是同步的,如果多个线程同时访问一个HashSet,如果有2条或者2条以上线程同时修改 了HashSet集合时,必须通过代码来保证其同步。
•集合元素值可以是null。
LinkedHashSet
•LinkedHashSet集合也是根据元素hashCode值来决定元素存储位置,但它同时使用链表维护元素的 次序,这样使得元素看起来是以插入的顺序保存的。也就是说,当遍历LinkedHashSet集合里元素 时,HashSet将会按元素的添加顺序来访问集合里的元素。
•LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的 全部元素时将有很好的性能,因为它以链表来维护内部顺序。
TreeSet
•TreeSet是SortedSet接口的唯一实现,正如SortedSet名字所暗示的,TreeSet可以确保集合元素 处于排序状态。与前面HashSet集合相比,TreeSet还提供了如下几个额外的方法: –Object first():返回集合中的第一个元素。 –Object last():返回集合中的最末一个元素。 –Object lower(Object e):返回集合中位于指定元素之前的元素(即小于指定元素的最大元 素,参考元素不需要是TreeSet的元素)。
–Object higher(Object e):返回集合中位于指定元素之后的元素(即大于指定元素的最小元 素,参考元素不需要是TreeSet的元素)。 –SortedSet subSet(fromElement, toElement):返回此Set的子集合,范围从 fromElement(包含)到toElement(不包含)。 –SortedSet headSet(toElement):返回此Set的子集,由小于toElement的元素组成。 –SortedSet tailSet(fromElement):返回此Set的子集,由大于或等于fromElement的元素组成。
TreeSet的排序
•TreeSet采用红黑树的数据结构对元素进行排序。TreeSet支持两种排序方法:自然排序和定制排 序。
–自然排序:TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系,然 后将集合元素按升序排列,这种方式就是自然排列。
–定制排序:TreeSet借助于Comparator接口的帮助。该接口里包含一个的int compare(T o1, T o2)方法,该方法用于比较o1和o2的大小。
EnumSet
•EnumSet是一个专为枚举类设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值 ,该枚举类型在创建EnumSet时显式或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以 枚举值在Enum类的定义顺序来决定集合元素的顺序。
•EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用内存 很小,而且运行效率很好。尤其是当进行批量操作(如调用containsAll 和 retainAll方法)时,如其参 数也是EnumSet集合,则该批量操作的执行速度也非常快。
•EnumSet集合不允许加入null元素。如果试图插入null元素,EnumSet将抛出 NullPointerException异常。如果仅仅只是试图测试是否出现null元素、或删除null元素都不会抛出异 常,只是删除操作将返回false,因为没有任何null元素被删除。
List接口
•List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可 以通过索引来访问指定位置的集合元素。因为List集合默认按元素的添加顺序设置元素的索引,例如第 一次添加的元素索引为0,第二次添加的元素索引为1……
•List作为Collection接口的子接口,当然可以使用Collection接口里全部方法。而且由于List是有序集 合,因此List集合里包含了根据索引来操作集合元素的方法。
ListIterator接口
•ListIterator与Iterator接口不同,它不仅可以向后迭代,它还可以向前迭代。 •ListIterator包含增加了如下3个方法: –boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素。 –Object previous():返回该迭代器的上一个元素。 –void add():在指定位置插入一个元素。
Iterator(迭代),Enumeration(枚举)
•迭代是取出集合中元素的一种方式。 •因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。
用法:
for(Iterator iter = iterator();iter.hasNext(); )
{
System.out.println(iter.next());
}
Iterator iter = l.iterator();
while(iter.hasNext())
{
System.out.println(iter.next());
}
迭代注意事项
•迭代器在Collcection接口中是通用的。 •迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。 •迭代器的next方法返回值类型是Object,所以要记得类型转换。
比较Comparator
比较函数强行对某些对象 collection 进行整体排序。可以将 Comparator 传递给 sort 方法(如 Collections.sort),从而允许在排序顺序上实现精确控制。
public class User {
int a;
String s;
public User(int a,String s) {
this.a=a;
this.s=s;
}
}
ArrayList<User> arr=new ArrayList();
arr.add(new User(21,"21"));
arr.add(new User(12,"12"));
arr.add(new User(3,"3"));
arr.add(new User(14,"14"));
arr.add(new User(5,"5"));
arr.add(new User(26,"26"));
Collections.sort(arr);
ArrayList与Vector
•ArrayList和Vector类都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态再分 配的Object[]数组。每个ArrayList或Vector对象有一个capacity属性,这个capacity表示它们所封 装的Object[]数组的长度。当向ArrayList或Vector中添加元素时,它们的capacity会自动增加。
•ArrayList和Vector的显著区别是;ArrayList是线程不安全的,当多条线程访问同一个ArrayList集 合时,如果有超过一条线程修改了ArrayList集合,则程序必须手动保证该集合的同步性。但Vector集 合则是线程安全的,无需程序保证该集合的同步性。
固定长度的List
•Arrays工具类里提供了asList(Object... a)方法,该方法可以把一个数组、或指定个数的对象转换 成一个List集合,这个List集合既不是ArrayList实现类的实例,也不是Vector实现类的实例,而是 Arrays的内部类ArrayList的实例。
•Arrays.ArrayList是一个固定长度的List集合,程序只能遍历访问该集合里的元素,不可增加、删除 该集合里的元素
Queue接口
•Queue用于模拟了队列这种数据结构,队列通常是指“先进先出”(FIFO)的容器。队列的头部保存 在队列中存放时间最长的元素。队列的尾部保存在队列中存放时间最短的元素。新元素插入(offer) 到队列的尾部,访问元素(poll)操作会返回队列头部的元素。通常,队列不允许随机访问队列中的元 素。
LinkedList
•它是List接口的实现类——这意味着它是一个List集合,可以根据索引来随机访问集合中的元素。除此 之外,LinkedList还实现了Deque接口,Deque接口是Queue接口的子接口,它代表一个双端队列。
•LinkedList不仅可以当成双端队列使用,也可以当成“栈”使用,因为该类里还包含了pop(出栈)和 push(入栈)两个方法。除此之外,LinkedList实现了List接口,所以还被当成List使用。
ArrayList与LinkedList
•LinkedList与ArrayList、Vector的实现机制完全不同,ArrayList、Vector内部以数组的形式来保 存集合中的元素,因此随机访问集合元素上有较好的性能;而LinkedList内部以链表的形式来保存集合 中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能非常出色(只需改变指针所 指的地址即可)。
类 Stack<E>
•java.util
•java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.Vector<E> java.util.Stack<E>
•所有已实现的接口: –Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
接口 Queue<E> •java.util
•类型参数: –E - 集合中所保存元素的类型。 •所有超级接口: –Collection<E>, Iterable<E> •所有已知子接口: –BlockingQueue<E> •所有已知实现类: –AbstractQueue, ArrayBlockingQueue, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingQueue, LinkedList, PriorityBlockingQueue, PriorityQueue,
PriorityQueue
•PriorityQueue是一个比较标准的队列实现类,之所以说它是比较标准的队列实现,而不是绝对标准 的队列实现是因为:PriorityQueue保存队列元素的顺序并不是按加入队列的顺序,而是按队列元素的 大小进行重新排序。因此当调用peek方法或者poll方法来取出队列中的元素时,并不是取出最先进入队 列的元素是,而是取出队列中最小的元素。
理解Map
•Map里key集和Set集合里元素的存储形式也很像,Map子类和Set子类在名字也惊人地相似:如Set 接口下有HashSet、LinkedHashSet、SortedSet(接口)、TreeSet、EnumSet等实现类和子接 口,而Map接口下则有HashMap、LinkedHashMap、SortedMap(接口)、TreeMap、 EnumMap等实现类和子接口。正如它们名字所暗示的,Map的这些实现类和子接口中key集存储形式 和对应Set集合中元素的存储形式完全相同。
•如果把Map所有value放在一起来看,它们又非常类似于一个List:元素与元素之间可以重复,每个元 素可以根据索引来查找,只是Map中的索引不再使用整数值,而是以另一个对象来作为索引。如果需要 从List集合中取出元素,需要提供该元素的数字索引。
HashMap和Hashtable
•HashMap和Hashtable都是Map接口的典型实现类,它们的区别如下: –Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比 Hashtable的性能高一点;但如果有多条线程访问同一个Map对象时,使用Hashtable实现类会更 好。
–Hashtable不允许使用null作为key和value,如果试图把null值放进Hashtable中,将会引发 NullPointerException异常;但HashMap可以使用null作为key或value。
LinkedHashMap
•LinkedHashMap也使用双向链表来维护key-value对的次序,该链表定义了迭代顺序,该迭代顺序 与key-value对的插入顺序保持一致。
•LinkedHashMap可以避免需要对HashMap、Hashtable里的key-value对进行排序(只要插入 key-value对时保持顺序即可)。同时又可避免使用TreeMap所增加的成本。
Map接口
•Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key, 另外一组值用于保存Map里的value,key和value都可以是任何引用类型的数据。Map的key不允许 重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。
•key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map 中取出数据时,只要给出指定的key,就可以取出对应的value。
Properties类
•Properties类是Hashtable类的子类,正如它的名字暗示的,该对象在处理属性文件时特别方便 (Windows操作平台上的ini文件就是一种属性文件)。Properties类可以把Map对象和属性文件关联 起来,从而可以把Map对象中的key-value对写入属性文件,也可以把属性文件中的属性名=属性值加 载到Map对象中。由于属性文件里的属性名、属性值只能是字符串类型,所以Properties里的key、 value都是字符串类型,该类提供了如下三个方法来修改Properties里的key、value值。
–String getProperty(String key):获取Properties中指定属性名对应的属性值,类似于Map 的get(Object key)方法。
–String getProperty(String key, String defaultValue):该方法与前一个方法基本相似。该 方法多一个功能,如果Properties中不存在指定key时,该方法返回默认值。
–Object setProperty(String key, String value):设置属性值,类似Hashtable 的put方法。
TreeMap
•Map接口也派生了一个SortedMap子接口,SortedMap也有一个TreeMap实现类。
•与TreeSet类似的是,TreeMap也是基于红黑树对TreeMap中所有key进行排序,从而保证 TreeMap中所有key-value对处于有序状态。TreeMap也有两种排序方式:
–自然排序:TreeMap的所有key必须实现Comparable接口,而且所有key应该是同一个类的对 象,否则将会抛出ClassCastException异常。
–定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中所有key 进行排序。采用定制排序时不要求Map的key实现Comparable接口。 WeakHashMap
•WeakHashMap与HashMap的用法基本相似。但与HashMap的区别在于,HashMap的key保留 对实际对象的强引用,这意味着只要该HashMap对象不被销毁,该HashMap对象所有key所引用的对 象不会被垃圾回收,HashMap也不会自动删除这些key所对应的key-value对象;
•但WeakHashMap的key只保留对实际对象的弱引用,这意味着如果该WeakHashMap对象所有 key所引用的对象没有被其他强引用变量所引用,则这些key所引用的对象可能被垃圾回收, WeakHashMap也可能自动删除这些key所对应的key-value对象。
IdentityHashMap
•IdentityHashMap实现类的实现机制与HashMap基本相似,但它在处理两个key相等时比较独特: 在IdentityHashMap中,当且仅当两个key严格相等(key1 == key2)时,IdentityHashMap才 认为两个键相等,
•对于普通HashMap而言,只要key1和key2通过equals比较返回true,且它们的hashCode值相等 即可。
EnumMap
•EnumMap是一个与枚举类一起使用的Map实现,EnumMap中所有key都必须是单个枚举类的枚举 值。创建EnumMap时必须显式或隐式指定它对应的枚举类。
•EnumMap在内部以数组形式保存,所以这种实现形式非常紧凑、高效。
•EnumMap根据key的自然顺序(即枚举值在枚举类中的定义顺序)来维护key-value对的次 序。当程序通过keySet()、entrySet()、values()等方法来遍历EnumMap时即可看到这种顺序。
•EnumMap不允许使用null作为key值,但允许使用null作为value。如果试图使用null作为key将抛出 NullPointerException异常。如果仅仅只是查询是否包含值为null的key、或者仅仅只是使用删除值为 null的key,都不会抛出异常。
HashSet和HashMap的性能
•因为HashSet和HashMap、Hashtable都使用hash算法来决定其元素(对HashMap则是key)的 存储,因此HashSet、HashMap的hash表包含如下属性:
–容量(capacity):hash表中桶的数量。
–初始化容量(initial capacity):创建hash表时桶的数量。HashMap和HashSet都允许在构造 器中指定初始化容量。
–尺寸(size):当前散列表中记录的数量。
–负载因子(load factor):负载因子等于“size/capacity”。负载因子为0,表示空的hash表, 0.5表示半满的散列表,依此类推。轻负载的散列表具有冲突少、适宜插入与查询的特点(但是使用 Iterator迭代元素时会变慢)。
Collections
•Java提供了一个操作Set、List和Map等集合的工具类:Collections,该工具类里提供了大量方法对 集合元素进行排序、查询和修改等操作。
•Collections还提供了将集合对象设置不可变、对集合对象实现同步控制等方法。
Enumeration接口
•Enumeration接口是Iterator迭代器的“古老版本”,从JDK1.0开始,Enumeration接口就已经存 在了(Iterator从JDK1.2才出现)。Enumeration 接口比Iterator小,只有两个名字很长的方法:
–boolean hasMoreElements( ):如果此迭代器还有剩下的元素则返回true。 –Object nextElement( ):返回该迭代器的下一个元素,如果还有的话(否则抛出异常)。
算法
•Collections 类中的静态方法 •用于排序、搜索、混排和数据操纵 •方法的第一个参数是要执行操作的集合 •重要异常 –ClassCastException –UnsupportedOperationException
class AlgorithmExample {
public static void main(String args[]) {
LinkedList link = new LinkedList();
link.add(new Integer(10));
link.add(new Integer(35));
link.add(new Integer(23));
link.add(new Integer(54));
link.add(new Integer(36));
Comparator cmp = Collections.reverseOrder();
Collections.sort(link, cmp);
Iterator it = link.iterator();
System.out.println("逆序排序的列表为: ");
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("给定列表中的最大值为:"+Collections.max(link));
System.out.println("给定列表中的最小值为:"+Collections.min(link));
}
}
集合框架的优点
•提供一组可用的集合接口 •提供有效的数据结构和算法 •可以方便地扩展或改写集合 •接口的实现都是可交换的 •使设计新 API 的工作降到最少 •接口和算法的可重用性
代码如下:
public class CollectionEach { public static void main(String[] args) { // 创建一个集合 Collection books = new HashSet(); books.add("轻量级Java EE企业应用实战"); books.add("疯狂Java讲义"); books.add("疯狂Android讲义"); // 调用forEach()方法遍历集合 books.forEach(obj -> System.out.println("迭代集合元素:" + obj)); } } ********************************************** public class CollectionStream { public static void main(String[] args) { // 创建books集合、为books集合添加元素 Collection books = new HashSet(); books.add(new String("轻量级Java EE企业应用实战")); books.add(new String("疯狂Java讲义")); books.add(new String("疯狂iOS讲义")); books.add(new String("疯狂Ajax讲义")); books.add(new String("疯狂Android讲义")); // 统计书名包含“疯狂”子串的图书数量 System.out.println(books.stream() .filter(ele->((String)ele).contains("疯狂")) .count()); // 输出4 // 统计书名包含“Java”子串的图书数量 System.out.println(books.stream() .filter(ele->((String)ele).contains("Java") ) .count()); // 输出2 // 统计书名字符串长度大于10的图书数量 System.out.println(books.stream() .filter(ele->((String)ele).length() > 10) .count()); // 输出2 // 先调用Collection对象的stream()方法将集合转换为Stream, // 再调用Stream的mapToInt()方法获取原有的Stream对应的IntStream books.stream().mapToInt(ele -> ((String)ele).length()) // 调用forEach()方法遍历IntStream中每个元素 .forEach(System.out::println);// 输出8 11 16 7 8 } } ******************************************** public class CollectionTest { public static void main(String[] args) { Collection c = new ArrayList(); // 添加元素 c.add("孙悟空"); // 虽然集合里不能放基本类型的值,但Java支持自动装箱 c.add(6); System.out.println("c集合的元素个数为:" + c.size()); // 输出2 // 删除指定元素 c.remove(6); System.out.println("c集合的元素个数为:" + c.size()); // 输出1 // 判断是否包含指定字符串 System.out.println("c集合的是否包含\"孙悟空\"字符串:" + c.contains("孙悟空")); // 输出true c.add("轻量级Java EE企业应用实战"); System.out.println("c集合的元素:" + c); Collection books = new HashSet(); books.add("轻量级Java EE企业应用实战"); books.add("疯狂Java讲义"); System.out.println("c集合是否完全包含books集合?" + c.containsAll(books)); // 输出false // 用c集合减去books集合里的元素 c.removeAll(books); System.out.println("c集合的元素:" + c); // 删除c集合里所有元素 c.clear(); System.out.println("c集合的元素:" + c); // 控制books集合里只剩下c集合里也包含的元素 books.retainAll(c); System.out.println("books集合的元素:" + books); } } ****************************************** public class ForeachTest { public static void main(String[] args) { // 创建集合、添加元素的代码与前一个程序相同 Collection books = new HashSet(); books.add(new String("轻量级Java EE企业应用实战")); books.add(new String("疯狂Java讲义")); books.add(new String("疯狂Android讲义")); for (Object obj : books) { // 此处的book变量也不是集合元素本身 String book = (String) obj; System.out.println(book); if (book.equals("疯狂Android讲义")) { // 下面代码会引发ConcurrentModificationException异常 books.remove(book); // ① } } System.out.println(books); } } ********************************************* public class IntStreamTest { public static void main(String[] args) { IntStream is = IntStream.builder() .add(20) .add(13) .add(-2) .add(18) .build(); // 下面调用聚集方法的代码每次只能执行一个 System.out.println("is所有元素的最大值:" + is.max().getAsInt()); System.out.println("is所有元素的最小值:" + is.min().getAsInt()); System.out.println("is所有元素的总和:" + is.sum()); System.out.println("is所有元素的总数:" + is.count()); System.out.println("is所有元素的平均值:" + is.average()); System.out.println("is所有元素的平方是否都大于20:" + is.allMatch(ele -> ele * ele > 20)); System.out.println("is是否包含任何元素的平方大于20:" + is.anyMatch(ele -> ele * ele > 20)); // 将is映射成一个新Stream,新Stream的每个元素是原Stream元素的2倍+1 IntStream newIs = is.map(ele -> ele * 2 + 1); // 使用方法引用的方式来遍历集合元素 newIs.forEach(System.out::println); // 输出41 27 -3 37 } } ***************************************** public class IteratorEach { public static void main(String[] args) { // 创建集合、添加元素的代码与前一个程序相同 Collection books = new HashSet(); books.add("轻量级Java EE企业应用实战"); books.add("疯狂Java讲义"); books.add("疯狂Android讲义"); // 获取books集合对应的迭代器 Iterator it = books.iterator(); // 使用Lambda表达式(目标类型是Comsumer)来遍历集合元素 it.forEachRemaining(obj -> System.out.println("迭代集合元素:" + obj)); } } **************************************** public class IteratorErrorTest { public static void main(String[] args) { // 创建集合、添加元素的代码与前一个程序相同 Collection books = new HashSet(); books.add("轻量级Java EE企业应用实战"); books.add("疯狂Java讲义"); books.add("疯狂Android讲义"); // 获取books集合对应的迭代器 Iterator it = books.iterator(); while (it.hasNext()) { String book = (String) it.next(); System.out.println(book); if (book.equals("疯狂Android讲义")) { // 使用Iterator迭代过程中,不可修改集合元素,下面代码引发异常 books.remove(book); } } } } **************************************** public class IteratorTest { public static void main(String[] args) { // 创建集合、添加元素的代码与前一个程序相同 Collection books = new HashSet(); books.add("轻量级Java EE企业应用实战"); books.add("疯狂Java讲义"); books.add("疯狂Android讲义"); // 获取books集合对应的迭代器 Iterator it = books.iterator(); while (it.hasNext()) { // it.next()方法返回的数据类型是Object类型,因此需要强制类型转换 String book = (String) it.next(); System.out.println(book); if (book.equals("疯狂Java讲义")) { // 从集合中删除上一次next方法返回的元素 it.remove(); } // 对book变量赋值,不会改变集合元素本身 book = "测试字符串"; // ① } System.out.println(books); } } ********************************************* public class PredicateTest { public static void main(String[] args) { // 创建一个集合 Collection books = new HashSet(); books.add(new String("轻量级Java EE企业应用实战")); books.add(new String("疯狂Java讲义")); books.add(new String("疯狂iOS讲义")); books.add(new String("疯狂Ajax讲义")); books.add(new String("疯狂Android讲义")); // 使用Lambda表达式(目标类型是Predicate)过滤集合 books.removeIf(ele -> ((String)ele).length() < 10); System.out.println(books); } } ***************************************** public class PredicateTest2 { public static void main(String[] args) { // 创建books集合、为books集合添加元素的代码与前一个程序相同。 Collection books = new HashSet(); books.add(new String("轻量级Java EE企业应用实战")); books.add(new String("疯狂Java讲义")); books.add(new String("疯狂iOS讲义")); books.add(new String("疯狂Ajax讲义")); books.add(new String("疯狂Android讲义")); // 统计书名包含“疯狂”子串的图书数量 System.out.println(calAll(books , ele->((String)ele).contains("疯狂"))); // 统计书名包含“Java”子串的图书数量 System.out.println(calAll(books , ele->((String)ele).contains("Java"))); // 统计书名字符串长度大于10的图书数量 System.out.println(calAll(books , ele->((String)ele).length() > 10)); } public static int calAll(Collection books, Predicate p) { int total = 0; for (Object obj : books) { // 使用Predicate的test()方法判断该对象是否满足Predicate指定的条件 if (p.test(obj)) { total++; } } return total; } }
enum Season { SPRING, SUMMER, FALL, WINTER } public class EnumSetTest { public static void main(String[] args) { // 创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值 EnumSet es1 = EnumSet.allOf(Season.class); System.out.println(es1); // 输出[SPRING,SUMMER,FALL,WINTER] // 创建一个EnumSet空集合,指定其集合元素是Season类的枚举值。 EnumSet es2 = EnumSet.noneOf(Season.class); System.out.println(es2); // 输出[] // 手动添加两个元素 es2.add(Season.WINTER); es2.add(Season.SPRING); System.out.println(es2); // 输出[SPRING,WINTER] // 以指定枚举值创建EnumSet集合 EnumSet es3 = EnumSet.of(Season.SUMMER, Season.WINTER); System.out.println(es3); // 输出[SUMMER,WINTER] EnumSet es4 = EnumSet.range(Season.SUMMER, Season.WINTER); System.out.println(es4); // 输出[SUMMER,FALL,WINTER] // 新创建的EnumSet集合的元素和es4集合的元素有相同类型, // es5的集合元素 + es4集合元素 = Season枚举类的全部枚举值 EnumSet es5 = EnumSet.complementOf(es4); System.out.println(es5); // 输出[SPRING] } } ****************************************** public class EnumSetTest2 { public static void main(String[] args) { Collection c = new HashSet(); c.clear(); c.add(Season.FALL); c.add(Season.SPRING); // 复制Collection集合中所有元素来创建EnumSet集合 EnumSet enumSet = EnumSet.copyOf(c); // ① System.out.println(enumSet); // 输出[SPRING,FALL] c.add("疯狂Java讲义"); c.add("轻量级Java EE企业应用实战"); // 下面代码出现异常:因为c集合里的元素不是全部都为枚举值 enumSet = EnumSet.copyOf(c); // ② } } ******************************************* // 类A的equals方法总是返回true,但没有重写其hashCode()方法 class A { public boolean equals(Object obj) { return true; } } // 类B的hashCode()方法总是返回1,但没有重写其equals()方法 class B { public int hashCode() { return 1; } } // 类C的hashCode()方法总是返回2,且重写其equals()方法总是返回true class C { public int hashCode() { return 2; } public boolean equals(Object obj) { return true; } } public class HashSetTest { public static void main(String[] args) { HashSet books = new HashSet(); // 分别向books集合中添加两个A对象,两个B对象,两个C对象 books.add(new A()); books.add(new A()); books.add(new B()); books.add(new B()); books.add(new C()); books.add(new C()); System.out.println(books); } } ******************************************** class R { int count; public R(int count) { this.count = count; } public String toString() { return "R[count:" + count + "]"; } public boolean equals(Object obj) { if (this == obj) return true; if (obj != null && obj.getClass() == R.class) { R r = (R) obj; return this.count == r.count; } return false; } public int hashCode() { return this.count; } } public class HashSetTest2 { public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new R(5)); hs.add(new R(-3)); hs.add(new R(9)); hs.add(new R(-2)); // 打印HashSet集合,集合元素没有重复 System.out.println(hs); // 取出第一个元素 Iterator it = hs.iterator(); R first = (R) it.next(); // 为第一个元素的count实例变量赋值 first.count = -3; // ① // 再次输出HashSet集合,集合元素有重复元素 System.out.println(hs); // 删除count为-3的R对象 hs.remove(new R(-3)); // ② // 可以看到被删除了一个R元素 System.out.println(hs); System.out.println("hs是否包含count为-3的R对象?" + hs.contains(new R(-3))); // 输出false System.out.println("hs是否包含count为-2的R对象?" + hs.contains(new R(-2))); // 输出false } } ******************************************* public class LinkedHashSetTest { public static void main(String[] args) { LinkedHashSet books = new LinkedHashSet(); books.add("疯狂Java讲义"); books.add("轻量级Java EE企业应用实战"); System.out.println(books); // 删除 疯狂Java讲义 books.remove("疯狂Java讲义"); // 重新添加 疯狂Java讲义 books.add("疯狂Java讲义"); System.out.println(books); } } ***************************************** class Err { } public class TreeSetErrorTest { public static void main(String[] args) { TreeSet ts = new TreeSet(); // 向TreeSet集合中添加两个Err对象 ts.add(new Err()); ts.add(new Err()); // ① } } ******************************************* public class TreeSetErrorTest2 { public static void main(String[] args) { TreeSet ts = new TreeSet(); // 向TreeSet集合中添加两个对象 ts.add(new String("疯狂Java讲义")); ts.add(new Date()); // ① } } ********************************************* public class TreeSetTest { public static void main(String[] args) { TreeSet nums = new TreeSet(); // 向TreeSet中添加四个Integer对象 nums.add(5); nums.add(2); nums.add(10); nums.add(-9); // 输出集合元素,看到集合元素已经处于排序状态 System.out.println(nums); // 输出集合里的第一个元素 System.out.println(nums.first()); // 输出-9 // 输出集合里的最后一个元素 System.out.println(nums.last()); // 输出10 // 返回小于4的子集,不包含4 System.out.println(nums.headSet(4)); // 输出[-9, 2] // 返回大于5的子集,如果Set中包含5,子集中还包含5 System.out.println(nums.tailSet(5)); // 输出 [5, 10] // 返回大于等于-3,小于4的子集。 System.out.println(nums.subSet(-3, 4)); // 输出[2] } } ****************************************** class Z implements Comparable { int age; public Z(int age) { this.age = age; } // 重写equals()方法,总是返回true public boolean equals(Object obj) { return true; } // 重写了compareTo(Object obj)方法,总是返回1 public int compareTo(Object obj) { return 1; } } public class TreeSetTest2 { public static void main(String[] args) { TreeSet set = new TreeSet(); Z z1 = new Z(6); set.add(z1); // 第二次添加同一个对象,输出true,表明添加成功 System.out.println(set.add(z1)); // ① // 下面输出set集合,将看到有两个元素 System.out.println(set); // 修改set集合的第一个元素的age变量 ((Z) (set.first())).age = 9; // 输出set集合的最后一个元素的age变量,将看到也变成了9 System.out.println(((Z) (set.last())).age); } } ****************************************** class R implements Comparable { int count; public R(int count) { this.count = count; } public String toString() { return "R[count:" + count + "]"; } // 重写equals方法,根据count来判断是否相等 public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null && obj.getClass() == R.class) { R r = (R) obj; return r.count == this.count; } return false; } // 重写compareTo方法,根据count来比较大小 public int compareTo(Object obj) { R r = (R) obj; return count > r.count ? 1 : count < r.count ? -1 : 0; } } public class TreeSetTest3 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new R(5)); ts.add(new R(-3)); ts.add(new R(9)); ts.add(new R(-2)); // 打印TreeSet集合,集合元素是有序排列的 System.out.println(ts); // ① // 取出第一个元素 R first = (R) ts.first(); // 对第一个元素的count赋值 first.count = 20; // 取出最后一个元素 R last = (R) ts.last(); // 对最后一个元素的count赋值,与第二个元素的count相同 last.count = -2; // 再次输出将看到TreeSet里的元素处于无序状态,且有重复元素 System.out.println(ts); // ② // 删除实例变量被改变的元素,删除失败 System.out.println(ts.remove(new R(-2))); // ③ System.out.println(ts); // 删除实例变量没有被改变的元素,删除成功 System.out.println(ts.remove(new R(5))); // ④ System.out.println(ts); } } ******************************************* class M { int age; public M(int age) { this.age = age; } public String toString() { return "M[age:" + age + "]"; } } public class TreeSetTest4 { public static void main(String[] args) { // 此处Lambda表达式的目标类型是Comparator TreeSet ts = new TreeSet((o1 , o2) -> { M m1 = (M)o1; M m2 = (M)o2; // 根据M对象的age属性来决定大小,age越大,M对象反而越小 return m1.age > m2.age ? -1 : m1.age < m2.age ? 1 : 0; }); ts.add(new M(5)); ts.add(new M(-3)); ts.add(new M(9)); System.out.println(ts); } }
public class FixedSizeList { public static void main(String[] args) { List fixedList = Arrays.asList("疯狂Java讲义" , "轻量级Java EE企业应用实战"); // 获取fixedList的实现类,将输出Arrays$ArrayList System.out.println(fixedList.getClass()); // 使用方法引用遍历集合元素 fixedList.forEach(System.out::println); // 试图增加、删除元素都会引发UnsupportedOperationException异常 fixedList.add("疯狂Android讲义"); fixedList.remove("疯狂Java讲义"); } } ***************************************** public class ListIteratorTest { public static void main(String[] args) { String[] books = { "疯狂Java讲义", "疯狂iOS讲义", "轻量级Java EE企业应用实战" }; List bookList = new ArrayList(); for (int i = 0; i < books.length; i++) { bookList.add(books[i]); } ListIterator lit = bookList.listIterator(); while (lit.hasNext()) { System.out.println(lit.next()); lit.add("-------分隔符-------"); } System.out.println("=======下面开始反向迭代======="); while (lit.hasPrevious()) { System.out.println(lit.previous()); } } } *************************************** public class ListTest { public static void main(String[] args) { List books = new ArrayList(); // 向books集合中添加三个元素 books.add(new String("轻量级Java EE企业应用实战")); books.add(new String("疯狂Java讲义")); books.add(new String("疯狂Android讲义")); System.out.println(books); // 将新字符串对象插入在第二个位置 books.add(1, new String("疯狂Ajax讲义")); for (int i = 0; i < books.size(); i++) { System.out.println(books.get(i)); } // 删除第三个元素 books.remove(2); System.out.println(books); // 判断指定元素在List集合中位置:输出1,表明位于第二位 System.out.println(books.indexOf(new String("疯狂Ajax讲义"))); // ① // 将第二个元素替换成新的字符串对象 books.set(1, new String("疯狂Java讲义")); System.out.println(books); // 将books集合的第二个元素(包括) // 到第三个元素(不包括)截取成子集合 System.out.println(books.subList(1, 2)); } } ****************************************** class A { public boolean equals(Object obj) { return true; } } public class ListTest2 { public static void main(String[] args) { List books = new ArrayList(); books.add(new String("轻量级Java EE企业应用实战")); books.add(new String("疯狂Java讲义")); books.add(new String("疯狂Android讲义")); System.out.println(books); // 删除集合中A对象,将导致第一个元素被删除 books.remove(new A()); // ① System.out.println(books); // 删除集合中A对象,再次删除集合中第一个元素 books.remove(new A()); // ② System.out.println(books); } } ***************************************** public class ListTest3 { public static void main(String[] args) { List books = new ArrayList(); // 向books集合中添加4个元素 books.add(new String("轻量级Java EE企业应用实战")); books.add(new String("疯狂Java讲义")); books.add(new String("疯狂Android讲义")); books.add(new String("疯狂iOS讲义")); // 使用目标类型为Comparator的Lambda表达式对List集合排序 books.sort((o1, o2)->((String)o1).length() - ((String)o2).length()); System.out.println(books); // 使用目标类型为UnaryOperator的Lambda表达式来替换集合中所有元素 // 该Lambda表达式控制使用每个字符串的长度作为新的集合元素 books.replaceAll(ele->((String)ele).length()); System.out.println(books); // 输出[7, 8, 11, 16] } }
public class ArrayDequeQueue { public static void main(String[] args) { ArrayDeque queue = new ArrayDeque(); // 依次将三个元素加入队列 queue.offer("疯狂Java讲义"); queue.offer("轻量级Java EE企业应用实战"); queue.offer("疯狂Android讲义"); // 输出:[疯狂Java讲义, 轻量级Java EE企业应用实战, 疯狂Android讲义] System.out.println(queue); // 访问队列头部的元素,但并不将其poll出队列"栈",输出:疯狂Java讲义 System.out.println(queue.peek()); // 依然输出:[疯狂Java讲义, 轻量级Java EE企业应用实战, 疯狂Android讲义] System.out.println(queue); // poll出第一个元素,输出:疯狂Java讲义 System.out.println(queue.poll()); // 输出:[轻量级Java EE企业应用实战, 疯狂Android讲义] System.out.println(queue); } } ****************************************** public class ArrayDequeStack { public static void main(String[] args) { ArrayDeque stack = new ArrayDeque(); // 依次将三个元素push入"栈" stack.push("疯狂Java讲义"); stack.push("轻量级Java EE企业应用实战"); stack.push("疯狂Android讲义"); // 输出:[疯狂Android讲义, 轻量级Java EE企业应用实战, 疯狂Java讲义] System.out.println(stack); // 访问第一个元素,但并不将其pop出"栈",输出:疯狂Android讲义 System.out.println(stack.peek()); // 依然输出:[疯狂Android讲义, 疯狂Java讲义, 轻量级Java EE企业应用实战] System.out.println(stack); // pop出第一个元素,输出:疯狂Android讲义 System.out.println(stack.pop()); // 输出:[轻量级Java EE企业应用实战, 疯狂Java讲义] System.out.println(stack); } } **************************************** public class LinkedListTest { public static void main(String[] args) { LinkedList books = new LinkedList(); // 将字符串元素加入队列的尾部 books.offer("疯狂Java讲义"); // 将一个字符串元素加入栈的顶部 books.push("轻量级Java EE企业应用实战"); // 将字符串元素添加到队列的头部(相当于栈的顶部) books.offerFirst("疯狂Android讲义"); // 以List的方式(按索引访问的方式)来遍历集合元素 for (int i = 0; i < books.size(); i++) { System.out.println("遍历中:" + books.get(i)); } // 访问、并不删除栈顶的元素 System.out.println(books.peekFirst()); // 访问、并不删除队列的最后一个元素 System.out.println(books.peekLast()); // 将栈顶的元素弹出“栈” System.out.println(books.pop()); // 下面输出将看到队列中第一个元素被删除 System.out.println(books); // 访问、并删除队列的最后一个元素 System.out.println(books.pollLast()); // 下面输出:[轻量级Java EE企业应用实战] System.out.println(books); } } ***************************************** public class PriorityQueueTest { public static void main(String[] args) { PriorityQueue pq = new PriorityQueue(); // 下面代码依次向pq中加入四个元素 pq.offer(6); pq.offer(-3); pq.offer(20); pq.offer(18); // 输出pq队列,并不是按元素的加入顺序排列 System.out.println(pq); // 输出[-3, 6, 20, 18] // 访问队列第一个元素,其实就是队列中最小的元素:-3 System.out.println(pq.poll()); } }
enum Season { SPRING, SUMMER, FALL, WINTER } public class EnumMapTest { public static void main(String[] args) { // 创建EnumMap对象,该EnumMap的所有key都是Season枚举类的枚举值 EnumMap enumMap = new EnumMap(Season.class); enumMap.put(Season.SUMMER, "夏日炎炎"); enumMap.put(Season.SPRING, "春暖花开"); System.out.println(enumMap); } } **************************************** public class HashMapErrorTest { public static void main(String[] args) { HashMap ht = new HashMap(); // 此处的A类与前一个程序的A类是同一个类 ht.put(new A(60000), "疯狂Java讲义"); ht.put(new A(87563), "轻量级Java EE企业应用实战"); // 获得Hashtable的key Set集合对应的Iterator迭代器 Iterator it = ht.keySet().iterator(); // 取出Map中第一个key,并修改它的count值 A first = (A) it.next(); first.count = 87563; // ① // 输出{A@1560b=疯狂Java讲义, A@1560b=轻量级Java EE企业应用实战} System.out.println(ht); // 只能删除没有被修改过的key所对应的key-value对 ht.remove(new A(87563)); System.out.println(ht); // 无法获取剩下的value,下面两行代码都将输出null。 System.out.println(ht.get(new A(87563))); // ② 输出null System.out.println(ht.get(new A(60000))); // ③ 输出null } } **************************************** class A { int count; public A(int count) { this.count = count; } // 根据count的值来判断两个对象是否相等。 public boolean equals(Object obj) { if (obj == this) return true; if (obj != null && obj.getClass() == A.class) { A a = (A) obj; return this.count == a.count; } return false; } // 根据count来计算hashCode值。 public int hashCode() { return this.count; } } class B { // 重写equals()方法,B对象与任何对象通过equals()方法比较都返回true public boolean equals(Object obj) { return true; } } public class HashtableTest { public static void main(String[] args) { Hashtable ht = new Hashtable(); ht.put(new A(60000), "疯狂Java讲义"); ht.put(new A(87563), "轻量级Java EE企业应用实战"); ht.put(new A(1232), new B()); System.out.println(ht); // 只要两个对象通过equals比较返回true, // Hashtable就认为它们是相等的value。 // 由于Hashtable中有一个B对象, // 它与任何对象通过equals比较都相等,所以下面输出true。 System.out.println(ht.containsValue("测试字符串")); // ① 输出true // 只要两个A对象的count相等,它们通过equals比较返回true,且hashCode相等 // Hashtable即认为它们是相同的key,所以下面输出true。 System.out.println(ht.containsKey(new A(87563))); // ② 输出true // 下面语句可以删除最后一个key-value对 ht.remove(new A(1232)); // ③ System.out.println(ht); } } ******************************************* public class IdentityHashMapTest { public static void main(String[] args) { IdentityHashMap ihm = new IdentityHashMap(); // 下面两行代码将会向IdentityHashMap对象中添加两个key-value对 ihm.put(new String("语文"), 89); ihm.put(new String("语文"), 78); // 下面两行代码只会向IdentityHashMap对象中添加一个key-value对 ihm.put("java", 93); ihm.put("java", 98); System.out.println(ihm); } } **************************************** public class LinkedHashMapTest { public static void main(String[] args) { LinkedHashMap scores = new LinkedHashMap(); scores.put("语文" , 80); scores.put("英文" , 82); scores.put("数学" , 76); // 调用forEach方法遍历scores里的所有key-value对 scores.forEach((key, value) -> System.out.println(key + "-->" + value)); } } ******************************************** public class MapTest { public static void main(String[] args) { Map map = new HashMap(); // 成对放入多个key-value对 map.put("疯狂Java讲义", 109); map.put("疯狂iOS讲义", 10); map.put("疯狂Ajax讲义", 79); // 多次放入的key-value对中value可以重复 map.put("轻量级Java EE企业应用实战", 99); // 放入重复的key时,新的value会覆盖原有的value // 如果新的value覆盖了原有的value,该方法返回被覆盖的value System.out.println(map.put("疯狂iOS讲义", 99)); // 输出10 System.out.println(map); // 输出的Map集合包含4个key-value对 // 判断是否包含指定key System.out.println("是否包含值为 疯狂iOS讲义 key:" + map.containsKey("疯狂iOS讲义")); // 输出true // 判断是否包含指定value System.out.println("是否包含值为 99 value:" + map.containsValue(99)); // 输出true // 获取Map集合的所有key组成的集合,通过遍历key来实现遍历所有key-value对 for (Object key : map.keySet()) { // map.get(key)方法获取指定key对应的value System.out.println(key + "-->" + map.get(key)); } map.remove("疯狂Ajax讲义"); // 根据key来删除key-value对。 System.out.println(map); // 输出结果不再包含 疯狂Ajax讲义=79 的key-value对 } } **************************************** public class MapTest2 { public static void main(String[] args) { Map map = new HashMap(); // 成对放入多个key-value对 map.put("疯狂Java讲义" , 109); map.put("疯狂iOS讲义" , 99); map.put("疯狂Ajax讲义" , 79); // 尝试替换key为"疯狂XML讲义"的value,由于原Map中没有对应的key, // 因此对Map没有改变,不会添加新的key-value对 map.replace("疯狂XML讲义" , 66); System.out.println(map); // 使用原value与参数计算出来的结果覆盖原有的value map.merge("疯狂iOS讲义" , 10 , (oldVal , param) -> (Integer)oldVal + (Integer)param); System.out.println(map); // "疯狂iOS讲义"的value增大了10 // 当key为"Java"对应的value为null(或不存在时),使用计算的结果作为新value map.computeIfAbsent("Java" , (key)->((String)key).length()); System.out.println(map); // map中添加了 Java=4 这组key-value对 // 当key为"Java"对应的value存在时,使用计算的结果作为新value map.computeIfPresent("Java", (key , value) -> (Integer)value * (Integer)value); System.out.println(map); // map中 Java=4 变成 Java=16 } } ****************************************** public class NullInHashMap { public static void main(String[] args) { HashMap hm = new HashMap(); // 试图将两个key为null的key-value对放入HashMap中 hm.put(null, null); hm.put(null, null); // ① // 将一个value为null的key-value对放入HashMap中 hm.put("a", null); // ② // 输出Map对象 System.out.println(hm); } } **************************************** public class PropertiesTest { public static void main(String[] args) throws Exception { Properties props = new Properties(); // 向Properties中增加属性 props.setProperty("username", "yeeku"); props.setProperty("password", "123456"); // 将Properties中的key-value对保存到a.ini文件中 props.store(new FileOutputStream("a.ini"), "comment line"); // ① // 新建一个Properties对象 Properties props2 = new Properties(); // 向Properties中增加属性 props2.setProperty("gender", "male"); // 将a.ini文件中的key-value对追加到props2中 props2.load(new FileInputStream("a.ini")); // ② System.out.println(props2); } } ******************************************* class R implements Comparable { int count; public R(int count) { this.count = count; } public String toString() { return "R[count:" + count + "]"; } // 根据count来判断两个对象是否相等。 public boolean equals(Object obj) { if (this == obj) return true; if (obj != null && obj.getClass() == R.class) { R r = (R) obj; return r.count == this.count; } return false; } // 根据count属性值来判断两个对象的大小。 public int compareTo(Object obj) { R r = (R) obj; return count > r.count ? 1 : count < r.count ? -1 : 0; } } public class TreeMapTest { public static void main(String[] args) { TreeMap tm = new TreeMap(); tm.put(new R(3), "轻量级Java EE企业应用实战"); tm.put(new R(-5), "疯狂Java讲义"); tm.put(new R(9), "疯狂Android讲义"); System.out.println(tm); // 返回该TreeMap的第一个Entry对象 System.out.println(tm.firstEntry()); // 返回该TreeMap的最后一个key值 System.out.println(tm.lastKey()); // 返回该TreeMap的比new R(2)大的最小key值。 System.out.println(tm.higherKey(new R(2))); // 返回该TreeMap的比new R(2)小的最大的key-value对。 System.out.println(tm.lowerEntry(new R(2))); // 返回该TreeMap的子TreeMap System.out.println(tm.subMap(new R(-1), new R(4))); } } ************************************** public class WeakHashMapTest { public static void main(String[] args) { WeakHashMap whm = new WeakHashMap(); // 将WeakHashMap中添加三个key-value对, // 三个key都是匿名字符串对象(没有其他引用) whm.put(new String("语文"), new String("良好")); whm.put(new String("数学"), new String("及格")); whm.put(new String("英文"), new String("中等")); // 将 WeakHashMap中添加一个key-value对, // 该key是一个系统缓存的字符串对象。 whm.put("java", new String("中等")); // ① // 输出whm对象,将看到4个key-value对。 System.out.println(whm); // 通知系统立即进行垃圾回收 System.gc(); System.runFinalization(); // 通常情况下,将只看到一个key-value对。 System.out.println(whm); } }
public class ArrayUtils { /** * 定义一个工具方法,工具方法从字符串数组中找到对应的字符串元素的位置 * * @param array * 搜索的数组 * @param target * 搜索的字符串 * @return 目标字符串出现的位置,-1表明找不到 */ public static int search(String[] array, String target) { for (int i = 0; i < array.length; i++) { if (array[i] != null && array[i].equals(target)) { return i; } } return -1; } } *************************************** public class SearchTest { public static void main(String[] args) { ArrayList nums = new ArrayList(); nums.add(2); nums.add(-5); nums.add(3); nums.add(0); System.out.println(nums); // 输出:[2, -5, 3, 0] System.out.println(Collections.max(nums)); // 输出最大元素,将输出3 System.out.println(Collections.min(nums)); // 输出最小元素,将输出-5 Collections.replaceAll(nums, 0, 1); // 将nums中的0使用1来代替 System.out.println(nums); // 输出:[2, -5, 3, 1] // 判断-5在List集合中出现的次数,返回1 System.out.println(Collections.frequency(nums, -5)); Collections.sort(nums); // 对nums集合排序 System.out.println(nums); // 输出:[-5, 1, 2, 3] // 只有排序后的List集合才可用二分法查询,输出3 System.out.println(Collections.binarySearch(nums, 3)); } } ****************************************** public class ShowHand { // 定义该游戏最多支持多少个玩家 private final int PLAY_NUM = 5; // 定义扑克牌的所有花色和数值. private String[] types = { "方块", "草花", "红心", "黑桃" }; private String[] values = { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" }; // cards是一局游戏中剩下的扑克牌 private List<String> cards = new LinkedList<String>(); // 定义所有的玩家 private String[] players = new String[PLAY_NUM]; // 所有玩家手上的扑克牌 private List<String>[] playersCards = new List[PLAY_NUM]; /** * 初始化扑克牌,放入52张扑克牌, 并且使用shuffle方法将它们按随机顺序排列 */ public void initCards() { for (int i = 0; i < types.length; i++) { for (int j = 0; j < values.length; j++) { cards.add(types[i] + values[j]); } } // 随机排列 Collections.shuffle(cards); } /** * 初始化玩家,为每个玩家分派用户名。 */ public void initPlayer(String... names) { if (names.length > PLAY_NUM || names.length < 2) { // 校验玩家数量,此处使用异常机制更合理 System.out.println("玩家数量不对"); return; } else { // 初始化玩家用户名 for (int i = 0; i < names.length; i++) { players[i] = names[i]; } } } /** * 初始化玩家手上的扑克牌,开始游戏时每个玩家手上的扑克牌为空, 程序使用一个长度为0的LinkedList来表示。 */ public void initPlayerCards() { for (int i = 0; i < players.length; i++) { if (players[i] != null && !players[i].equals("")) { playersCards[i] = new LinkedList<String>(); } } } /** * 输出全部扑克牌,该方法没有实际作用,仅用作测试 */ public void showAllCards() { for (String card : cards) { System.out.println(card); } } /** * 派扑克牌 * * @param first * 最先派给谁 */ public void deliverCard(String first) { // 调用ArrayUtils工具类的search方法, // 查询出指定元素在数组中的索引 int firstPos = ArrayUtils.search(players, first); // 依次给位于该指定玩家之后的每个玩家派扑克牌 for (int i = firstPos; i < PLAY_NUM; i++) { if (players[i] != null) { playersCards[i].add(cards.get(0)); cards.remove(0); } } // 依次给位于该指定玩家之前的每个玩家派扑克牌 for (int i = 0; i < firstPos; i++) { if (players[i] != null) { playersCards[i].add(cards.get(0)); cards.remove(0); } } } /** * 输出玩家手上的扑克牌 实现该方法时,应该控制每个玩家看不到别人的第一张牌,但此处没有增加该功能 */ public void showPlayerCards() { for (int i = 0; i < PLAY_NUM; i++) { // 当该玩家不为空时 if (players[i] != null) { // 输出玩家 System.out.print(players[i] + " : "); // 遍历输出玩家手上的扑克牌 for (String card : playersCards[i]) { System.out.print(card + "\t"); } } System.out.print("\n"); } } public static void main(String[] args) { ShowHand sh = new ShowHand(); sh.initPlayer("电脑玩家", "孙悟空"); sh.initCards(); sh.initPlayerCards(); // 下面测试所有扑克牌,没有实际作用 sh.showAllCards(); System.out.println("---------------"); // 下面从"孙悟空"开始派牌 sh.deliverCard("孙悟空"); sh.showPlayerCards(); /* * 这个地方需要增加处理: 1.牌面最大的玩家下注. 2.其他玩家是否跟注? 3.游戏是否只剩一个玩家?如果是,则他胜利了。 * 4.如果已经是最后一张扑克牌,则需要比较剩下玩家的牌面大小. */ // 再次从"电脑玩家"开始派牌 sh.deliverCard("电脑玩家"); sh.showPlayerCards(); } } **************************************** public class SortTest { public static void main(String[] args) { ArrayList nums = new ArrayList(); nums.add(2); nums.add(-5); nums.add(3); nums.add(0); System.out.println(nums); // 输出:[2, -5, 3, 0] Collections.reverse(nums); // 将List集合元素的次序反转 System.out.println(nums); // 输出:[0, 3, -5, 2] Collections.sort(nums); // 将List集合元素的按自然顺序排序 System.out.println(nums); // 输出:[-5, 0, 2, 3] Collections.shuffle(nums); // 将List集合元素的按随机顺序排序 System.out.println(nums); // 每次输出的次序不固定 } } ****************************************** public class SynchronizedTest { public static void main(String[] args) { // 下面程序创建了四个线程安全的集合对象 Collection c = Collections.synchronizedCollection(new ArrayList()); List list = Collections.synchronizedList(new ArrayList()); Set s = Collections.synchronizedSet(new HashSet()); Map m = Collections.synchronizedMap(new HashMap()); } } ********************************************* public class UnmodifiableTest { public static void main(String[] args) { // 创建一个空的、不可改变的List对象 List unmodifiableList = Collections.emptyList(); // 创建一个只有一个元素,且不可改变的Set对象 Set unmodifiableSet = Collections.singleton("疯狂Java讲义"); // 创建一个普通Map对象 Map scores = new HashMap(); scores.put("语文", 80); scores.put("Java", 82); // 返回普通Map对象对应的不可变版本 Map unmodifiableMap = Collections.unmodifiableMap(scores); // 下面任意一行代码都将引发UnsupportedOperationException异常 unmodifiableList.add("测试元素"); // ① unmodifiableSet.add("测试元素"); // ② unmodifiableMap.put("语文", 90); // ③ } }
public class EnumerationTest { public static void main(String[] args) { Vector v = new Vector(); v.add("疯狂Java讲义"); v.add("轻量级Java EE企业应用实战"); Hashtable scores = new Hashtable(); scores.put("语文", 78); scores.put("数学", 88); Enumeration em = v.elements(); while (em.hasMoreElements()) { System.out.println(em.nextElement()); } Enumeration keyEm = scores.keys(); while (keyEm.hasMoreElements()) { Object key = keyEm.nextElement(); System.out.println(key + "--->" + scores.get(key)); } } }
|





浙公网安备 33010602011771号