java程序员从笨鸟到菜鸟之(三十二)集合之集合实用类

集合高级特性

在前面我们介绍了数组的工具类:Arrays,本节我们开始介绍Collections的工具类

特点:

1    位于java.util.Collections(所以必须导包),所提供的均是静态方法(不需要创建实例对象)

2    一部分专门操纵List类型集合,另个一部分操纵所有的Collections类型或Map类型

注意事项:看API文档时,必须了解相关方法的参数和返回值类型

常用成员方法介绍

public static <T> void sort(List<T> list):排序,默认按照自然顺序
public static <T> int binarySearch(List<?> list,T key):二分查找
public static <T> T max(Collection<?> coll):获取最大值
public static void reverse(List<?> list):反转
public static void shuffle(List<?> list):随机置换
说明:对这些方法的由来感兴趣的话可以看一看底层源码----有助于理解其包装过程

实例1

package demo;

import java.util.ArrayList;
import java.util.Collections;

/**
 * @author Orange
 * @version 1.8
 */
public class Demo06 {
	public static void main(String[] args) {
		ArrayList<Integer> list = new ArrayList<Integer>();//默认排序,实现Comparable接口
		list.add(3);
		list.add(-5);
		list.add(1);
		list.add(0);
		list.add(10);
		Collections.sort(list);                   //排序
		System.out.println(list);
		int s = Collections.binarySearch(list, 1);//二分查找
		System.out.println(s);
		Collections.reverse(list);                //翻转
		System.out.println(list);
		Collections.shuffle(list);                //随机置换
		System.out.println(list);
	}
	
}
实例2

需求:模拟斗地主的洗牌和发牌,牌没有排序

  分析:
  (1)首先得有容器存储牌,然后生成54张牌
  (2)新牌总得洗洗吧!老规则先切牌,再洗两次牌
  (3)开始发牌,如何发牌呢?----面向过程的思维
  (4)发完牌总得看看手里面的牌,才能决定是否叫地主

package demo;

import java.util.ArrayList;
import java.util.Collections;

/**
 * @author Orange
 * @version 1.8
 */

public class Demo7 {
     public static void main(String[] args) {
       ArrayList<String> arrayList = new ArrayList<String>();
       //买牌---装牌
       String[] st={"♠","♥","♦","♣"};//四种花色,静态初始化
       String[] stNu={"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
       for(int i=0;i<st.length;i++){
    	   for(int j=0;j<stNu.length;j++){
    		   arrayList.add(st[i]+stNu[j]);//将牌存储到牌盒种,"+"是不是太low了,换成contact
    	   }
       }
       arrayList.add("☀");//大王
       arrayList.add("☾");//小王
       System.out.println(arrayList);
       System.out.println("牌买来了,买牌不容易呀!!!");
       for(int i=0;i<2;i++){
    	   Collections.shuffle(arrayList);//洗牌---三次:一人一次
       }
       System.out.println(arrayList.size());
       //发牌前---发给三个人---三个斗地主----每个人的牌是一堆,三个容器接受各自的牌
       ArrayList<String> kangKang = new ArrayList<String>();
       ArrayList<String> jane = new ArrayList<String>();
       ArrayList<String> tony = new ArrayList<String>();
       ArrayList<String> cards = new ArrayList<String>();
       //正式发牌
       for(int i=0;i<arrayList.size()-1;i++){
    	   if(i>arrayList.size()-5){
    		   cards.add(arrayList.get(i));
    	   }else if(i%3==0){
    		   kangKang.add(arrayList.get(i));
    	   }else if(i%3==1){
    		   jane.add(arrayList.get(i));
    	   }else{
    		   tony.add(arrayList.get(i));
    	   }
    	   //注意:if --else if特点:一旦匹配,下面就不再执行了
       }
       //看牌吧!!!
       System.out.println(kangKang);
       System.out.println(jane);
       System.out.println(tony);
       System.out.println(cards);        
	}
}

说明:牌全是用ArrayList进行储存

升级:我是初学者,有点懒不想自己插牌,你给我按照大小自动生成牌,且按照花色"♠","♥","♦","♣"排列

分析:显然现在是要进行排序的,说起排序你可能会想到用TreeMap的有参和无参构造方法实现自然排序和客户端排序;由于TreeMap是对键对象进行排序的,我们可以将新牌设定一个顺序,也即采用键值对的形式,如下所示(图的来源来自网上,有一定错误):


注意一点:与上面练习的的区别就是要进行排序了,先按照大小,后按照花色进行排列,每一张索引对应一张牌。在这个过程中,洗牌的话洗的是索引(将索引单独放到一个ArrayList容器中),给每个人发的也是索引,每个人接受牌的索引所储存的容器也是TreeMap,这样就保证了每个人得到牌的索引已经按照大小和花色进行排列,所以只需要按照牌的索引找牌顺序输出即可

实例2

package demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

/**
 * @author Orange
 * @version 1.8
 */
public class Demo8 {
	public static void main(String[] args) {
		//牌盒
	     HashMap<Integer, String> tm = new HashMap<Integer,String>();
		//放牌
	     String[] color={"♠","♥","♦","♣"};//四种花色,静态初始化
	     String[] num={"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
	     int index=0;//每张牌的索引
	     ArrayList<Integer> al = new ArrayList<Integer>();//存储牌的索引
	     //用增强for循环代替普通for循环---花色
	     for(String st:num){
	    	 for(String str:color){
	    		 tm.put(index,st.concat(str));//将牌存储到牌盒种
	    		 al.add(index);
	    		 index++;
	    	 }
	     }
	     al.add(++index);
	     al.add(++index);
	     /**
	      * 错误的做法:集合的元素与上一次元素已经不一样了
	      * 这次:0-----梅花1
	      *       0-----方砖1
	      *       0-----红桃1
	      *       0-----黑桃1
	      * 分析:与上次的玄机在于先添加牌的大小还是先添加颜色
	      * 思考?按花色排---然后才是大小
	      */
	     tm.put(++index,"☀");//大王
	     tm.put(++index,"☾");//小王
	     //System.out.println(tm);//看看牌盒子的牌的索引 
	     //发牌,老一套----保存各自的牌
	     TreeSet<Integer> kangKang = new TreeSet<>();
	     TreeSet<Integer> jane = new TreeSet<>();
	     TreeSet<Integer> linDa = new TreeSet<>();
	     TreeSet<Integer> cards = new TreeSet<>();
	     
	     //洗牌--洗的是索引
	     for(int i=0;i<2;i++){
	    	   Collections.shuffle(al);//洗牌---三次
	       }
	     System.out.println(al);//洗好后的牌索引
	     //发牌---54张牌,其中3张底牌
	     for(int i=0;i<tm.size();i++){
	    	 if(i>tm.size()-4){//三张底牌
	    		 cards.add(al.get(i));//得到牌的索引
	    	 }else if(i%3==0){
	    		 kangKang.add(al.get(i));
	    	 }else if(i%3==1){
	    		 jane.add(al.get(i));
	    	 }else{
	    		 linDa.add(al.get(i));
	    	 }
	     }
	     //得到牌的索引---可以找到牌,将牌添加到底牌中
	     /*
	     System.out.println(kangKang);
	     System.out.println(jane);
	     System.out.println(linDa);
	     System.out.println(cards);
	               说明:输出结果主要说明牌的索引已经自动排序了
	     */
	     //按照花色进行排列,按理说底牌不用排序(思考下怎么处理?)
	     method("kangKang",tm,kangKang);
	     method("jane",tm,jane);
	     method("linDa",tm,linDa);
	     method("cards",tm,cards);
	     //如果是按花色呢?集合不变
	}

/**
 * @param tm
 * @param kangKang
 *        按照花色进行排列---"♠","♥","♦","♣"
 */
private static void method(String s,HashMap<Integer, String> tm, TreeSet<Integer> name) {
	System.out.println(s+"的牌:");
	for(Integer in:name){
		 String string = tm.get(in);
		 System.out.print(string+" ");
	 }
	 System.out.println();
}

}

数组和集合的互换---联系

首先回顾集合与数组的区别

(1)把集合转化为数组

查看API文档的描述:


注意:这个方法的参数是用了可变的参数(jdk5后的特性),而这里可变的参数可以写不确定个数的参数,也可以直接用一个数组替代。记住,如果参数是数组,只能是一个数组,不可以是多个;如果是多个的话,前面就应该换成List<String[]>,里面的String必须换String数组才行。

实例3

package demo;

import java.util.Arrays;
import java.util.List;

/**
 * @author Orange
 * @version 1.8
 */
public class ArrayToCollections {
	 
	  //数组转化成集合
	 
    public static void main(String[] args) {
         
        Integer[] demo=new Integer[5];
        demo[0]=1;
        demo[1]=2;
        demo[2]=3;
        demo[3]=4;
        demo[4]=5;
        List<Integer> list = Arrays.asList(demo);//数组中的Integer元素直接转化成list集合中的元素,Integer是一个引用类型
        System.out.println(list);
    }
}
实例4

package demo;

import java.util.Arrays;
import java.util.List;

/**
 * @author Orange
 * @version 1.8
 */
public class ArrayToCollections {
	 //多个数组的形式
    public static void main(String[] args) {
         
        int[] demo1=new int[5];
        demo1[0]=1;
        demo1[1]=2;
        demo1[2]=3;
        demo1[3]=4;
        demo1[4]=5;
        List<int[]> asList2 = Arrays.asList(demo1);//注意与上述的区别,int[]是一个引用类型
        for(int[] s:asList2){//遍历集合中的元素
        	for(int s1:s){
        	    System.out.print(s1+" ");
        	}
        }
        System.out.println();
    }
}
思考:分析实例3与实例4的原因?明确一点集合只可以储存引用类型
实例5

package demo;

import java.util.Arrays;
import java.util.List;

/**
 * @author Orange
 * @version 1.8
 */
public class ArrayToCollections {
	 //多个数组的形式
    public static void main(String[] args) {
         
        int[] demo1=new int[5];
        demo1[0]=1;
        demo1[1]=2;
        demo1[2]=3;
        demo1[3]=4;
        demo1[4]=5;
        int[] demo2=new int[5];
        demo2[0]=6;
        demo2[1]=7;
        demo2[2]=8;
        demo2[3]=9;
        demo2[4]=10;
       //多个数组,可变参数的形式
       List<int[]> asList = Arrays.asList(demo1,demo2);//自动装箱
       for(int[] s:asList){//List集合储存的是引用类型---int[]
    	   for(int s1:s)  {
    		   System.out.print(s1+" ");
    	   } 
    	   System.out.println();
       }    
       /**
        * 刷新了认识:
        * foreach可以遍历数组(基本和引用类型)和集合(引用类型)
        * asList()方法返回值类型取决于数组中元素的类型
        */
    }
}
实例6

package demo;

import java.util.Arrays;
import java.util.List;

/**
 * @author Orange
 * @version 1.8
 */
public class ArrayToCollections {
	// 多个数组的形式
	public static void main(String[] args) {

		String[] demo1 = new String[5];
		demo1[0] = "1";
		demo1[1] = "2";
		demo1[2] = "3";
		demo1[3] = "4";
		demo1[4] = "5";
		String[] demo2 = new String[5];
		demo2[0] = "6";
		demo2[1] = "7";
		demo2[2] = "8";
		demo2[3] = "9";
		demo2[4] = "10";
		// 多个数组,可变参数的形式
		List<String> asList2 = Arrays.asList(demo1);        // 参数单个数组
		for (String s : asList2) {
			System.out.print(s+" ");
		}
		System.out.println();
		List<String[]> asList = Arrays.asList(demo1, demo2);// 参数多个数组
		for (String[] s : asList) {
			for (String s1 : s) {
				System.out.print(s1 + " ");
			}
			System.out.println();
		}

	}
}

集合转化为数组

toArray函数有两种形式,一种无参数,一种带参数,注意带参数形式中,要指明数组的大小

方式1  无参的形式



说明:对于此种方法由于返回值类型是Object(表明可以接受任意类型),要还原原始的类型必须向下转型
实例7

package demo;

import java.util.ArrayList;

/**
 * @author Orange
 * @version 1.8
 */
public class CollectionToArray {
	public static void main(String[] args) {
		ArrayList<Integer> arrLi = new ArrayList<Integer>();
		for (int i = 0; i < 10; i++) {
			arrLi.add(i);
		}
        //方式1
		Object[] array = arrLi.toArray();
		for(int i=0;i<array.length;i++){
			Integer inte=(Integer)array[i];
			/**
			 * 说明:
			 * (1)数组存储的是Object类型
			 * (2)其实将Integer向上转型为Object类型
			 */
			System.out.print(inte+" ");
		}
	}
}
方式2  有参的形式


实例8

package demo;

import java.util.ArrayList;

/**
 * @author Orange
 * @version 1.8
 */
public class CollectionToArray1 {
	public static void main(String[] args) {
		ArrayList<Integer> arrLi = new ArrayList<Integer>();
		for (int i = 0; i < 10; i++) {
			arrLi.add(i);
		}
	        //方式2---不存在转型问题,但必须明确数组存储的类型
		//在转换成数组时,在参数中已经创建出了接受集合的数组
		//注意:集合的存储类型必须与数组的存储类型相匹配
		Integer[] array = arrLi.toArray(new Integer[arrLi.size()]);//一定要指明数组的大小
		//遍历
		for(Integer a:array){
			System.out.print(a+" ");
		}
	}
	
}
问题:上面asList方法只能转换成list,怎么转换成Set或Queue呢?

解决思路:集合里面所有的具体类的构造方法都有一个方法的参数是Collection,所以这里已经有了list了,可以将这个list作为参数,直接再通过构造方法new出来一个其他的集合就可以了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值