根据多态,集合类如果不使用泛型就会装任何类,因为所有类都是Object的子类,所以一个集合类的实例是可以装不同类的实例的。不过在取出这些实例时必须强制类型转换,不然会在编译时报错!看如下实例:
package com.csdn.abc;
import java.util.ArrayList;
public class First {
@SuppressWarnings("unchecked")
public static void main(String[] args){
ArrayList apples = new ArrayList();
for(int i = 0; i < 3; i++){
apples.add(new Apple());
}
apples.add(new Orange());
for(int i = 0; i < apples.size(); i++){
System.out.println(((Apple) apples.get(i)).id());
}
}
}
class Apple{
private static long counter;
private final long id = counter++;
public long id(){
return id;
}
}
class Orange{
}
ArrayList的实例能同时装Apple与Orange的实例,因为它们都是Object的子类。
运行实例,输出:
0
1
2
Exception in thread "main" java.lang.ClassCastException: com.Orange cannot be cast to com.Apple
at com.First.main(First.java:15)
把Orange类型强制转为Apple类型会在运行时报错。
为了避免这种错误,需要使用泛型规定集合类中存放的数据类型,避免出现不同的类型!
把上面的ArrayList apples = new ArrayList();
改为 ArrayList
这样当往apples中存放Oranle类型的实例就会报错,这是报错就是编译时报错,而不是运行时报错。
运用泛型后,取出元素时,强制类型转换就不需要了!
集合类分为两种
(1)Collection
包括List(按照插入顺序保存数据,按照索引查找元素,可理解为长度可变的数组),Set(不能有重复元素),Queue(队列)。
(2)Map
以键值对的形式存在。
实例:
package com;
import java.util.ArrayList;
import java.util.Collection;
public class Two {
public static void main(String[] args) {
Collection c = new ArrayList();
for(int i = 0; i < 10; i++){
c.add(i);
}
for(Integer i:c){
System.out.print(i+", ");
}
}
}
add()方法把元素添加进集合,List的add()方法总是将元素添加进集合,但对于Set来说,add()方法不一定会添加元素,因为Set集合不允许重复,所以Set在添加前要检查是否有重复值。
所有的Collection都可以用foreach遍历,另外们还有“迭代器”可以更灵活的遍历集合。
在一个Collection中添加一组元素有两种方法
方法一:Arrays.asList()方法接受一个用逗号分隔的元素列表(即可变参数),然后将其转换为List对象:
package com;
import java.util.Arrays;
import java.util.List;
public class Three {
public static void main(String[] args) {
List list = Arrays.asList(1,2,3);
for(int i:list){
System.out.print(i+", ");//输出1, 2, 3,
}
}
}
这种方法生成的集合只是像集合,其实不是集合,而是一个数组,不能对其进行添加和删除!
方法二:new Collection().addAll()方法接受一个集合,将此集合添加到Collection中:
package com;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class Four {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(0);
List list = Arrays.asList(1,2,3);
collection.addAll(list);
for(int i:collection){
System.out.print(i+", ");//输出0, 1, 2, 3,
}
}
}
方法三:Collections.addAll()方法接受一个集合对象和一个用逗号分隔的列表:
package com;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
public class Five {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(0);
Collections.addAll(collection,1,2,3,4);
for(int i:collection){
System.out.print(i+", ");//输出0, 1, 2, 3, 4,
}
}
}
在第四版的《java编程思想》中,这三种方法除了能添加一组参数,还能添加一个集合,但是我用的java8不支持添加集合!!!
书有点老了,没钱买第五版,第五版全是正版的!!!
书中下面代码:
package com;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Six {
public static void main(String[] args) {
List snow1 = Arrays.asList(new Crusty(),new Slush(),new Powder());
List snow2 = Arrays.asList(new Light(),new Heavy());
List snow3 = new ArrayList();
Collections.addAll(snow3,new Light(),new Heavy());
List snow4 = Arrays.asList(new Light(),new Heavy());
}
}
class Snow{}
class Powder extends Snow{}
class Light extends Powder{}
class Heavy extends Powder{}
class Crusty extends Snow{}
class Slush extends Snow{}
按书中所说,snow2变量会报错,因为 Arrays.asList(new Light(),new Heavy())
返回的是 List
,而不是 List
但我亲测,不会报错!!!
编译器在不断进步啊!!!
先看例子:
package com;
import java.util.*;
public class Seven {
public static void main(String[] args) {
System.out.println(fill(new ArrayList()));
System.out.println(fill(new LinkedList()));
System.out.println(fill(new HashSet()));
System.out.println(fill(new TreeSet()));
System.out.println(fill(new LinkedHashSet()));
System.out.println(fill(new HashMap()));
System.out.println(fill(new TreeMap()));
System.out.println(fill(new LinkedHashMap()));
}
static Collection fill(Collection collection){
collection.add("rat");
collection.add("cat");
collection.add("dog");
collection.add("dog");
return collection;
}
static Map fill(Map map){
map.put("rat","Fuzzy");
map.put("cat","Rags");
map.put("dog","Bosco");
map.put("dog","sqot");
return map;
}
}
/*
输出:
[rat, cat, dog, dog]
[rat, cat, dog, dog]
[rat, cat, dog]
[cat, dog, rat]
[rat, cat, dog]
{rat=Fuzzy, cat=Rags, dog=sqot}
{cat=Rags, dog=sqot, rat=Fuzzy}
{rat=Fuzzy, cat=Rags, dog=sqot}
*/
从中可以看出,set不允许重复,map的键不允许重复,带Tree字符串的类还将元素进行了排序!!!
写代码学习集合方法:
package com;
import java.util.*;
public class Eight {
public static void main(String[] args) {
List list = new ArrayList();
Collections.addAll(list,new A(),new B(),new C(),new D());
//打印集合
System.out.println("1:"+list);
//add()方法添加元素
E e = new E();
list.add(e);
System.out.println("2:"+list);
//contains()方法判断元素是否在集合中
System.out.println("3:"+list.contains(e));
//remove()方法删除元素
list.remove(e);
//get()方法根据索引返回元素
Word word = list.get(1);
//indexOf()方法根据元素返回索引
System.out.println("4:元素为:"+word+" 索引为:"+list.indexOf(word));
Word b = new B();
//虽然list中有B类的对象,但list中的B的对象与上一行的b并不是同一对象
//所以下面将返回-1,b并且删除不会成功
System.out.println("5:"+list.indexOf(b));
System.out.println("6:"+list.remove(b));
//因为word是根据索引取出的,所以删除成功
System.out.println("7:"+list.remove(word));
System.out.println("8:"+list);
//根据索引添加元素
list.add(1,new E());
System.out.println("9:"+list);
List list2 = new ArrayList();
Collections.addAll(list2,new A(),new C());
System.out.println("10:"+list2);
//containAll()方法判断集合是否包含另一个集合
System.out.println("11:"+list.containsAll(list2));
List copy = new ArrayList(list);
list2 = Arrays.asList(list.get(1),list.get(3));
System.out.println("12:"+list2);
//retainAll()方法取交集并添加到调用的对象中
copy.retainAll(list2);
System.out.println("13:"+copy);
copy = new ArrayList(list);
System.out.println("14:"+copy);
//根据索引删除
copy.remove(1);
System.out.println("15:"+copy);
//removeAll()方法从copy中删除list2中的所有元素
copy.removeAll(list2);
System.out.println("16:"+copy);
//根据索引线删除再添加,即修改
copy.set(1,new B());
System.out.println("17:"+copy);
//指定索引添加集合
copy.addAll(0,list2);
System.out.println("18:"+copy);
//isEmpty()方法判断是否为空
System.out.println("19:"+ list.isEmpty());
//toArray()方法将集合转为数组,无参数返回Object
Object[] o = list.toArray();
System.out.println("20:"+o[1]);
//返回Word类型的数组
Word[] o1 = list.toArray(new Word[0]);
System.out.println("21:"+o1[1]);
//cleat()方法清空集合
list.clear();
System.out.println("22:"+ list);
}
}
class Word{}
class A extends Word{}
class B extends Word{}
class C extends Word{}
class D extends Word{}
class E extends Word{}
/*
输出:
1:[com.A@1db9742, com.B@106d69c, com.C@52e922, com.D@25154f]
2:[com.A@1db9742, com.B@106d69c, com.C@52e922, com.D@25154f, com.E@10dea4e]
3:true
4:元素为:com.B@106d69c 索引为:1
5:-1
6:false
7:true
8:[com.A@1db9742, com.C@52e922, com.D@25154f]
9:[com.A@1db9742, com.E@647e05, com.C@52e922, com.D@25154f]
10:[com.A@1909752, com.C@1f96302]
11:false
12:[com.E@647e05, com.D@25154f]
13:[com.E@647e05, com.D@25154f]
14:[com.A@1db9742, com.E@647e05, com.C@52e922, com.D@25154f]
15:[com.A@1db9742, com.C@52e922, com.D@25154f]
16:[com.A@1db9742, com.C@52e922]
17:[com.A@1db9742, com.B@14eac69]
18:[com.E@647e05, com.D@25154f, com.A@1db9742, com.B@14eac69]
19:false
20:com.E@647e05
21:com.E@647e05
22:[]
*/
迭代器用于遍历集合元素,比foreach语法更为灵活!看代码:
package com;
import java.util.*;
public class Nine {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(0);
Collections.addAll(collection,1,2,3,4,5,6,7,8);
//iterator()方法生成一个迭代器对象
Iterator it = collection.iterator();
//hasNext()方法判断是否还有下一个元素
while(it.hasNext()){
//next()方法取出下一个元素
int sum = it.next();
System.out.print(sum+", ");
}
System.out.println();
for(int i:collection){
System.out.print(i+", ");
}
it = collection.iterator();
System.out.println();
for(int i = 0; i < 3; i++){
it.next();
it.remove();
}
System.out.println(collection);
}
}
/*输出:
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
[3, 4, 5, 6, 7, 8]
*/
当迭代器遍历到最后并不会重新 ,所以想再次使用,必须再次调用iterator()方法
package com;
import java.util.*;
public class Ten {
public static void main(String[] args) {
Collection collection = new ArrayList();
Collections.addAll(collection,0,1,2,3,4,5,6,7,8);
LinkedList linkedList = new LinkedList(collection);
HashSet hashSet = new HashSet(collection);
TreeSet treeSet = new TreeSet(collection);
display(collection.iterator());
display(linkedList.iterator());
display(hashSet.iterator());
display(treeSet.iterator());
}
public static void display(Iterator it){
while(it.hasNext()){
int sum = it.next();
System.out.print(sum+", ");
}
System.out.println();
}
}
/*
输出:
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
*/
iterator()只能向前遍历,而不能想后遍历。使用listIterator()方法能够实现向后遍历:
package com;
import java.util.*;
public class ListIteratorDemo {
public static void main(String[] args) {
ArrayList collection = new ArrayList();
collection.add(0);
Collections.addAll(collection,1,2,3,4);
ListIterator it = collection.listIterator();
while(it.hasNext()){
System.out.print(it.next()+","+it.nextIndex()+","+it.previousIndex()+";");
}
System.out.println();
while(it.hasPrevious()){
System.out.print(it.previous()+",");
}
System.out.println();
System.out.print(collection);
it = collection.listIterator(2);
while(it.hasNext()){
it.next();
it.set(5);
}
System.out.println(collection);
}
}
/*
输出:
0,1,0;1,2,1;2,3,2;3,4,3;4,5,4;
4,3,2,1,0,
[0, 1, 2, 3, 4][0, 1, 5, 5, 5]
*/
一些方法的使用:
package com;
import java.util.*;
public class LinkedListFeatures {
public static void main(String[] args) {
ArrayList collection = new ArrayList();
collection.add(0);
Collections.addAll(collection,1,2,3,4,5,6,7);
LinkedList linked = new LinkedList(collection);
System.out.println(linked);
//getFirst()与element()与peek()方法都返回集合的第一个元素
System.out.println(linked.getFirst());
System.out.println(linked.element());
System.out.println(linked.peek());
System.out.println(linked.remove());
System.out.println(linked.removeFirst());
System.out.println(linked);
linked.addFirst(8);
System.out.println(linked);
linked.addLast(9);
System.out.println(linked);
linked.removeLast();
System.out.println(linked);
}
}
使用LinkedList实现栈的功能,先定义一个栈类:
package com;
import java.util.*;
public class Stack {
private LinkedList storage = new LinkedList();
public void push(T v){
storage.addFirst(v);
}
public T peek(){
return storage.getFirst();
}
public T pop(){
return storage.removeFirst();
}
public boolean empty(){
return storage.isEmpty();
}
public String toString(){
return storage.toString();
}
}
测试类
package com;
public class StackTest {
public static void main(String[] args) {
Stack stack = new Stack();
for(String s:"my dog has fleas".split(" ")){
stack.push(s);
}
while(!stack.empty()){
System.out.println(stack.pop()+" ");
}
}
}
java API中本来就有Stack类,但是设计欠佳,多以用LinkedList这种方式代替原本的Stack更好!
Set集合不允许有重复的元素,Set最常用的就是测试归属性,可以很容易的询问某个对象是否在某个Set中。正因如此,查找就成了Set最重要的操作。
存放Integer对象的HashSet示例:
package com;
import java.util.*;
public class SetOfInteger {
public static void main(String[] args) {
Random rand = new Random(47);
Set intset = new HashSet();
for(int i = 0;i < 10000; i++){
intset.add(rand.nextInt(30));
}
System.out.println(intset);
}
}
/*
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
*/
关于为何Set集合遍历后是有序的问题,这里我百度了一下,在知乎找到了答案:
实现是会变的,HashSet的迭代器在输出时“不保证有序”,但也不是“保证无序”。也就是说,输出时有序也是允许的,但是你的程序不应该依赖这一点。
TreeSet会将集合内的对象就行排序
Set最常见的操作就是使用contains()测试Set的归属性,下面是Set方法的一些示例:
package com;
import java.util.*;
public class SetOperations {
public static void main(String[] args) {
Set set1 = new HashSet();
Collections.addAll(set1,"A,B,C,D,E,F,G,H,I,J,K,L".split(","));
set1.add("M");
//contains()方法测试集合中是否包含元素
System.out.println("H:"+set1.contains("H"));
System.out.println("N:"+set1.contains("N"));
Set set2 = new HashSet();
Collections.addAll(set2,"H,I,J,K".split(","));
//containsAll()方法测试集合中是否包含另一个元素
System.out.println(set1.containsAll(set2));
set1.remove("H");
System.out.println(set1.containsAll(set2));
set1.removeAll(set2);
System.out.println(set1);
}
}
package com;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class Statistics {
public static void main(String[] args) {
Random rand = new Random(47);
Map<Integer,Integer> m = new HashMap<Integer,Integer>();
for(int i = 0; i < 10000;i++){
int r = rand.nextInt(20);
Integer freq = m.get(r);
m.put(r, freq == null?1:freq+1);
}
System.out.println(m);
}
}
/*
输出:
{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, 7=471, 8=468, 9=549, 10=513, 11=531, 12=521, 13=506, 14=477, 15=497, 16=533, 17=509, 18=478, 19=464}
*/
实例中键是1-20,值则是10000次中,键出现的次数
LinkedList提供了方法以支持队列的行为,并且他实现了Queue接口,可以通过Linked向上转型为Queue,下列实例使用了Queue
package com;
import java.util.*;
public class QueueDemo {
public static void printQ(Queue queue){
//peek()方法返回队列的队首
while(queue.peek()!=null){
System.out.print(queue.remove()+" ");
}
System.out.println();
}
public static void main(String[] args) {
Queue queue = new LinkedList();
Random rand = new Random(47);
//offer()方法将元素添加到队尾
for(int i = 0; i< 10;i++){
queue.offer(rand.nextInt(i+10));
}
printQ(queue);
Queue qc = new LinkedList();
for(char c:"Brontosaurus".toCharArray()){
qc.offer(c);
}
printQ(qc);
}
}
当使用PriorityQueue插入对象时,这个对象会在队列中排序!
看实例:
package com;
import java.util.*;
public class PriorityQueueDemo {
public static void main(String[] args) {
PriorityQueue priorityQueue = new PriorityQueue();
Random rand = new Random(47);
for(int i = 0;i < 10; i++){
priorityQueue.offer(rand.nextInt(i+10));
}
QueueDemo.printQ(priorityQueue);
List ints = Arrays.asList(25,22,20,18,14,9,3,1,1,2,3,9,14,18,21,23,25);
priorityQueue = new PriorityQueue(ints);
QueueDemo.printQ(priorityQueue);
priorityQueue = new PriorityQueue(ints.size(),Collections.reverseOrder());
priorityQueue.addAll(ints);
QueueDemo.printQ(priorityQueue);
String fact = "EDUCATTION SHOULD ESCHEW OBFUSCATION";
List strings = Arrays.asList(fact.split(" "));
PriorityQueue stringPQ = new PriorityQueue(strings);
QueueDemo.printQ(stringPQ);
stringPQ = new PriorityQueue(strings.size(),Collections.reverseOrder());
stringPQ.addAll(strings);
QueueDemo.printQ(stringPQ);
Set charSet = new HashSet();
for(char c:fact.toCharArray()){
charSet.add(c);
}
PriorityQueue charcterPQ = new PriorityQueue(charSet);
QueueDemo.printQ(charcterPQ);
}
}
PriorityQueue有两个构造器,一个是构造器是直接添加集合,另一个是给出队列长度!
Collections.reverseOrder()代表了反序!
PriorityQueue会对队列就行排序!
最后一个Set元素用于将字母去重。
package com;
import java.util.*;
public class InterfaceVsIterator {
public static void display(Iterator ints){
while(ints.hasNext()){
int i = ints.next();
System.out.print(i+" ");
}
System.out.println();
}
public static void display(Collection col){
for(int i:col){
System.out.print(i+" ");
}
System.out.println();
}
public static void main(String[] args) {
List list = Arrays.asList(25,22,20,18);
Set set = new HashSet<>(list);
Map map = new LinkedHashMap();
String[] name = "a b c d".split(" ");
for(int i = 0; i < name.length; i++){
map.put(name[i], list.get(i));
}
display(list);
display(set);
display(list.iterator());
display(set.iterator());
System.out.println(map);
System.out.println(map.keySet());
display(map.values());
display(map.values().iterator());
}
}
迭代器和foreach都可以遍历集合!
如果继承Collection接口就必须在子类中实现很多方法!
通过集成Collection的一个抽象类AbstractCollection可以避免实现过多的方法,不过需要实现iterator()方法!
package com;
import java.util.*;
public class CollectionSequence extends AbstractCollection {
private Integer[] ints = {1,2,3,4};
@Override
public Iterator iterator() {
return new Iterator(){
private int index = 0;
@Override
public boolean hasNext() {
return index < ints.length;
}
@Override
public Integer next() {
return ints[index++];
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
@Override
public int size() {
return ints.length;
}
public static void main(String[] args){
CollectionSequence c = new CollectionSequence();
InterfaceVsIterator.display(c);
InterfaceVsIterator.display(c.iterator());
}
}
CollectionSequence类会根据iterator()方法判断集合中包含是哪个数组!
有点不懂!百度了一下,得知:foreach内部也是采用了Iterator的方式实现,只不过Java编译器帮我们生成了这些代码。
恩,懂了
下面实例不需要集成AbstractCollection但需要使用itreator()遍历,itreator()自己实现!
package com;
import java.util.*;
class IntSequence{
protected int[] ints = {1,2,3,4};
}
public class NonCollectionSequence extends IntSequence{
public Iterator iterator(){
return new Iterator(){
private int index = 0;
@Override
public boolean hasNext() {
return index < ints.length;
}
@Override
public Integer next() {
return ints[index++];
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
NonCollectionSequence n = new NonCollectionSequence();
InterfaceVsIterator.display(n.iterator());
}
}
package com;
import java.util.*;
public class ForEachCollection {
public static void main(String[] args) {
Collection cs = new LinkedList();
Collections.addAll(cs,"Take me Long way home".split(" "));
for(String s : cs){
System.out.print(s+" ");
}
}
}
Iterable接口被foreach用来在序列中移动
代码和12节示例一样
打印环境变量:
package com;
import java.util.*;
public class EnvironmentVariables {
public static void main(String[] args) {
for(Map.Entry entry:System.getenv().entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
foreach可以用于数组和任何其他Iterable.
但是数组不是Iterable!看如下实例;
package com;
import java.util.Arrays;
public class ArrayIsNotIterable {
static void test(Iterable id){
for(T t : id){
System.out.print(t+" ");
}
System.out.println();
}
public static void main(String[] args) {
test(Arrays.asList(1,2,3));
String[] strings = {"A","B","C"};
//下面会报错
//test(strings);
for(String s : strings){
System.out.print(s+" ");
}
System.out.println();
test(Arrays.asList(strings));
}
}
适配器方法模式有点不懂!,不过没问题,理解下面代码还是可以的。
下面代码实现了反向迭代!需要添加一个能够产生Iterable对象的方法,该对象用于foreach语句,
package com;
import java.util.*;
public class AdapterMethodIdiom {
public static void main(String[] args) {
ReversibleArrayList ral = new ReversibleArrayList<>(
Arrays.asList("To be or not to be".split(" ")));
for(String s: ral){
System.out.print(s+" ");
}
System.out.println();
for(String s:ral.reversed()){
System.out.print(s+" ");
}
}
}
class ReversibleArrayList extends ArrayList{
public ReversibleArrayList(Collection c){
super(c);
}
public Iterable reversed(){
return new Iterable(){
@Override
public Iterator iterator() {
return new Iterator(){
private int current = size()-1;
public boolean hasNext(){
return current > -1;
}
public T next(){
return get(current--);
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
};
}
}
这里先实现了返回Iterable对象的方法,在返回的对象中,重写了iterator()方法,使得反向迭代的逻辑可以实现!
在foreach语句的for(String s:ral.reversed())
调用反向迭代的方法可见,只要冒号后面的语句返回的对象中实现iterator方法就可以使用foreach!foreach会自动调用iterator()
下列代码实现了一个类实现三种不同的foreach迭代方法
package com;
import java.util.*;
public class MultiIterableClass implements Iterable{
private String[] words = {"abc","def","ghi","jkl","mn"};
public Iterator iterator() {
return new Iterator(){
private int index = 0;
@Override
public boolean hasNext() {
return index < words.length;
}
@Override
public String next() {
return words[index++];
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
public Iterable reversed(){
return new Iterable(){
@Override
public Iterator iterator() {
return new Iterator(){
private int current = words.length - 1;
public boolean hasNext(){
return current > -1;
}
public String next(){
return words[current--];
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
};
}
public Iterable randomized(){
return new Iterable(){
public Iterator iterator(){
List shuffled = new ArrayList<>(Arrays.asList(words));
Collections.shuffle(shuffled,new Random(47));
return shuffled.iterator();
}
};
}
public static void main(String[] args){
MultiIterableClass mu = new MultiIterableClass();
for(String s : mu.reversed()){
System.out.print(s+" ");
}
System.out.println();
for(String s : mu.randomized()){
System.out.print(s+" ");
}
System.out.println();
for(String s : mu){
System.out.print(s+" ");
}
}
}
/*
输出:
mn jkl ghi def abc
ghi abc mn def jkl
abc def ghi jkl mn
*/
Collections.shuffle()方法打乱了集合中的引用。
因为randomized()方法将一个ArrayList将Arrays.asList()方法的结果包装了起来,所以words没有被打乱,但如果没有用ArrayList包装,words将会被打乱!如下实例:
package com;
import java.util.*;
public class ModifyingArrayAsList {
public static void main(String[] args) {
Random rand = new Random(47);
Integer[] ia = {1,2,3,4,5,6,7,8};
List list = new ArrayList<>(Arrays.asList(ia));
System.out.println(list);
Collections.shuffle(list,rand);
System.out.println(list);
System.out.println(Arrays.toString(ia));
System.out.println("------");
List list2 = Arrays.asList(ia);
System.out.println(list2);
Collections.shuffle(list2,rand);
System.out.println(list2);
System.out.println(Arrays.toString(ia));
}
}
/*
输出:
[1, 2, 3, 4, 5, 6, 7, 8]
[5, 4, 7, 1, 8, 2, 3, 6]
[1, 2, 3, 4, 5, 6, 7, 8]
------
[1, 2, 3, 4, 5, 6, 7, 8]
[7, 3, 1, 5, 8, 2, 6, 4]
[7, 3, 1, 5, 8, 2, 6, 4]
*/