7.8 操作集合的工具类:Collections

Posted weststar

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7.8 操作集合的工具类:Collections相关的知识,希望对你有一定的参考价值。

一、排序操作

Collections提供了如下常用类方法用于对List集合进行排序:
★void reverse(List list):反转指定的List集合中的元素顺序。
★void shuffle(List list):对Lsit集合中的元素进行随机排序(shuffle方法模仿了”洗牌“动作)。
★void sort(List list):根据元素的自然顺序对指定集合元素按升序进行排序。
★void sort(List list,Comparator compare):根据指定Comparator产生顺序对List集合进行排序。
★void swap(List list,int i,int j):交换List集合中的索引i处和索引j处的元素。
★void rotate(Lsit list,int distance):当distance为整数时,将list集合后distance个元素”整体“移到前面;当distance为负数时,将list集合的前distance个元素整体移到后面。该方法不会改变集合的长度。
下面程序示范了利用Collections工具类来操作list集合:

import static java.util.Collections.*;
import java.util.ArrayList;
public class SortTest 
{
	public static void main(String[] args) 
	{
		var nums=new ArrayList();
		nums.add(2);
		nums.add(-5);
		nums.add(3);
		nums.add(0);
		//原始排序
		System.out.println(nums);//[2, -5, 3, 0]
		//将list集合反转排序
		reverse(nums);
		System.out.println(nums);//[0, 3, -5, 2]
		//按照List集合元素的自然顺序排序,调用元素Comparable接口中的caompreTo()方法
		sort(nums);
		System.out.println(nums);//[-5, 0, 2, 3]
		//随机排序
		shuffle(nums);
		System.out.println(nums);//[-5, 3, 0, 2]
	}
}

上面程序示范了Collection类常用排序操作。下面是一个梭哈柚子来演示List集合、Collection工具类的强大功能。

import java.util.*;
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<>();
	// 定义所有的玩家
	private String[] players = new String[PLAY_NUM];
	// 所有玩家手上的扑克牌
	private List<String>[] playersCards = new List[PLAY_NUM];

	/**
	 * 初始化扑克牌,放入52张扑克牌,
	 * 并且使用shuffle方法将它们按随机顺序排列
	 */
	public void initCards()
	{
		for (var i = 0; i < types.length; i++)
		{
			for (var 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 (var i = 0; i < names.length; i++)
			{
				players[i] = names[i];
			}
		}
	}
	/**
	 * 初始化玩家手上的扑克牌,开始游戏时每个玩家手上的扑克牌为空,
	 * 程序使用一个长度为0的LinkedList来表示。
	 */
	public void initPlayerCards()
	{
		for (var i = 0; i < players.length; i++)
		{
			if (players[i] != null && !players[i].equals(""))
			{
				playersCards[i] = new LinkedList<String>();
			}
		}
	}
	/**
	 * 输出全部扑克牌,该方法没有实际作用,仅用作测试
	 */
	public void showAllCards()
	{
		for (var card : cards )
		{
			System.out.println(card);
		}
	}
	/**
	 * 派扑克牌
	 * @param first 最先派给谁
	 */
	public void deliverCard(String first)
	{
		// 调用Arrays工具类的binarySearch()方法,   报错空指针异常
		// 查询出指定元素在数组中的索引
		int firstPos=6;
		for(int i=0;i<players.length;i++)
		{
			if(players[i].equals(first))
			{
				firstPos=i;
				break;
			}
		}	
		System.out.println("系统发牌中...");
		
//		var firstPos = Arrays.binarySearch(players, first);
		// 依次给位于该指定玩家之后的每个玩家派扑克牌
		for (var i = firstPos; i < PLAY_NUM; i++)
		{
			if (players[i] != null)
			{
				playersCards[i].add(cards.get(0));
				cards.remove(0);
			}
		}
		// 依次给位于该指定玩家之前的每个玩家派扑克牌
		for (var i = 0; i < firstPos; i++)
		{
			if (players[i] != null)
			{
				playersCards[i].add(cards.get(0));
				cards.remove(0);
			}
		}
	}
	/**
	 * 输出玩家手上的扑克牌
	 * 实现该方法时,应该控制每个玩家看不到别人的第一张牌,但此处没有增加该功能
	 */
	public void showPlayerCards()
	{
		for (var i = 0; i < PLAY_NUM; i++)
		{
			// 当该玩家不为空时
			if (players[i] != null)
			{
				// 输出玩家
				System.out.print(players[i] + " : " );
				// 遍历输出玩家手上的扑克牌
				for (var card : playersCards[i])
				{
					System.out.print(card + "	");
				}
			}
			System.out.print("
");
		}
	}
	public static void main(String[] args)
	{
		var 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();
		sh.deliverCard("孙悟空");
		sh.showPlayerCards();
	}
}

二、查找和替换功能

Collection还提供了如下常用查找、替换元素的类方法
★int binarySearch(List list,Object key):使用二分法搜索指定List集合,以获取指定对象在List集合中的索引。如果该方法可以正常工作,则必须保证List元素以及处于有序状态。
★Object max(Collection coll):更具元素自然排序,返回给定集合中的最大元素。
★Object max(Collection coll,Comparator compare):根据Comparator指定顺序,返回给定集合中的最大元素。
★Object min(Collection coll):更具元素自然排序,返回给定集合中的最小元素。
★Object min(Collection coll,Comparator compare):根据Comparator指定顺序,返回给定集合中的最小元素。
★void fill(List list,Object obj):使用指定元素obj替换指定List集合中的所有元素。
★int frequency(Collection c,Object o):返回指定集合中指定元素出现的次数。
★int indexOfSubList(List source,List target):返回子List对象在父List对象中第一次出现的位置索引;如果父List对象中没有出现这样的子List,则返回-1。
★int lastIndexOfSubList(List source,List target):返回子List对象在父List对象中最后一次出现的位置索引;如果父List对象中没有出现这样的子List,则返回-1。
★boolean repalceAll(List list,Object oldVal,Object newVal):使用一个新值newVal替换List对象的所有旧值oldVal。
Collections工具类的用法:

import java.util.ArrayList;
import java.util.Collections;
public class SearchTest 
{
	public static void main(String[] args) 
	{
		var 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
		//将nums中的0使用1代替
		Collections.replaceAll(nums,0,1);
		System.out.println(nums);//[2, -5, 3, 1]
		//判断-5在List集合中出现的次数,返回0
		System.out.println(Collections.frequency(nums,-5));//1


		//对nums自然排序
		Collections.sort(nums);
		System.out.println(nums);//[-5, 1, 2, 3]
		//使用二分法查找元素
		System.out.println(Collections.binarySearch(nums,2));//2
	}
}

三、同步控制

Collections类中提供了多个synchronizedXxx()方法,该方法可以将集合包装成线程同步的集合,从而解决多线程并发访问集合时的线程安全问题。
Java中常用集合框架中的实现类HashSet、TreeSet、ArrayList、ArrayDeque、LinkedList、HashMap和treeMap都是线程不安全的。如果多个线程访问它们,而且有超过一个的线程试图修改它们,则它们存在线程安全问题。Collections提供了多个类方法可以把它们包装成线程同步的集合。


import java.util.*;
public class SynchronizedTest
{
	public static void main(String[] args)
	{
		// 下面程序创建了四个线程安全的集合对象
		var c = Collections
			.synchronizedCollection(new ArrayList());
		var list = Collections.synchronizedList(new ArrayList());
		var s = Collections.synchronizedSet(new HashSet());
		var m = Collections.synchronizedMap(new HashMap());
	}
}

四、设置不可变集合

Collections提供如下三个方法来返回一个不可变集合:
1、emptyXxx():返回一个空的不可变的集合对象,此处的集合可以是List、SortedSet、Set、Map、TreeMap等。
2、singletonXxx():返回一个只包含指定对象(只有一个或一项元素)的、不可变的集合对象,此处的集合可以是List,也可以是Map。省略Xxx则是set
3、unmodifiableXxx():返回指定集合对象的不可变视图,此处的集合可以是List、SortedSet、Set、Map、TreeMap等。
上面三类方法的参数是原有的集合对象,返回值是该集合的"只读"版本。通过Collections提供的三类方法,可以生成只读的Collection或Map

import java.util.*;
public class unmodifiableTest
{
	public static void main(String[] args)
	{
		//创建一个空的不可变的List对象
		var unmodifiableList=Collections.emptyList();
		//创建一个只有一个元素、且不可变的Set对象
		var unmodifiableSet=Collections.singleton("疯狂Java讲义");
		//创建一个普通的Map对象
		var scores=new HashMap();
		scores.put("语文",90);
		scores.put("数学",98);

		//返回普通的Map对象对应的不可变版本
		var unmodifiableMap=Collections.unmodifiableMap(scores);

		//下面三条语句将引发Exception in thread "main" java.lang.UnsupportedOperationException
		unmodifiableList.add("测试元素");
		unmodifiableSet.add("测试元素");
		unmodifiableMap.put("语文",92);
	}
}

五、Java 9新增的不可变集合

在以前如果需要创建一个包含6个元素的Set集合,程序需要先创建Set集合,然后调用6次add()方法向Set集合中添加元素。Java 9对此进行简化,程序直接调用Set、List、Map的of()方法即可创建包含N个元素的不可变集合,这样一行代码就可以创建包含N个元素的集合。
不可变以为着不能向集合中添加元素,也不能从集合中删除元素。

import java.util.*;
public class Java9Collection
{
	public static void main(String[] args)
	{
		//创建包含4个元素的Set集合
		var set=Set.of("Java","Kotlin","Go","Swift");
		System.out.println(set);
		//不可变集合,下面将导致运行时错误
		//set.add("Ruby");//Exception in thread "main" java.lang.UnsupportedOperationException

		//创建4个对象的List集合
		var list=List.of(34,5,64,45);
		System.out.println(list);
		//不可变集合,下面将导致运行时错误
		//list.remove(5);//Exception in thread "main" java.lang.UnsupportedOperationException

		// 创建包含3组key-value对的Map集合
		var map = Map.of("语文", 89, "数学", 82, "英语", 92);
		System.out.println(map);
		// 不可变集合,下面代码导致运行时错误
//		map.remove("语文");
		// 使用Map.entry()方法显式构建key-value对
		var map2 = Map.ofEntries(Map.entry("语文", 89),
			Map.entry("数学", 82),
			Map.entry("英语", 92));
		System.out.println(map2);
	}
}
---------- 运行Java捕获输出窗 ----------
[Go, Swift, Java, Kotlin]
[34, 5, 64, 45]
{语文=89, 数学=82, 英语=92}
{语文=89, 数学=82, 英语=92}

输出完成 (耗时 0 秒) - 正常终止

以上是关于7.8 操作集合的工具类:Collections的主要内容,如果未能解决你的问题,请参考以下文章

跟王老师学集合:操作集合的工具类:Collections

操作集合的工具类:Collections

Java集合框架—— Collections工具类

Collections 工具类

Collections 工具类

Java Review (三十集合----- 操作集合的工具类: Collections)