行业资讯
【南京java开发】java集合框架是什么?(五)
2019-10-22

记得关注,点赞,转发……………………………………………………………………………………………………………………………………………………………………………………………………………………

 


 

分享继续

 

Map接口中的共性功能:

 

    1.添加:

        v put(key, value):当存储的键相同时,新的值会替换老的值,并将老值返回。如果键没有重复,返回null

        putAll(Map<k,v> map);

 

    2.删除:

        void clear():清空

        v remove(key):删除指定键- -> 会改变集合长度!

 

    3.判断:

        boolean containsKey(Object key):是否包含key

        boolean containsValue(Object value):是否包含value

        boolean isEmpty();

 

    4.取出:

        v get(key):通过指定键获取对应的值。如果返回null,可以判断该键不存在。

                             当然有特殊情况,就是在hashmap集合中,是可以存储nullnull值的。

        int size():返回长度。

 

    代码示例:

 

package ustc.maxiaolun.map;

 

import java.util.HashMap;

import java.util.Map;

 

public class MapDemo {

 

public static void main(String[] args) {

/*

 * 需求:Map集合中存储学号、姓名。

 */

Map<Integer, String> map = new HashMap<Integer, String>();

methodDemo(map);

}

public static void methodDemo(Map<Integer, String> map){

 

//1.存储键值对。如果键相同,会出现值覆盖。

System.out.println(map.put(3, "xiaoqiang"));

System.out.println(map.put(3, "erhu"));

map.put(7, "wangcai");

map.put(2, "daniu");

 

//2.移除。-->会改变长度。

//System.out.println(map.remove(7));

 

//3.获取。

System.out.println(map.get(7));

 

System.out.println(map);

}

}

      5.想要获取Map中的所有元素:

    原理:map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,可以使用迭代器了。之所以转成set,是因为map集合具备着键的唯一性,其实set集合就来自于mapset集合底层其实用的就是map的方法。

    把Map集合转成Set的方法:

 

    方式1: Set keySet();

 

    可以将map集合中的键都取出存放到set集合中。对set集合进行迭代。迭代完成,再通过get方法对获取到的键进行值的获取。

 

 

 

Set keySet = map.keySet();

Iterator it = keySet.iterator();

while(it.hasNext()) {

Object key = it.next();

Object value = map.get(key);

System.out.println(key+":"+value);

}

     方式2: Set entrySet(); 

 

     取的是键和值的映射关系。Map.Entry:其实就是一个Map接口中的内部接口。为什么要定义在map内部呢?entry是访问键值关系的入口,是map的入口,访问的是map中的键值对。

 

 

 

Set entrySet = map.entrySet();

Iterator it = entrySet.iterator();

while(it.hasNext()) {

Map.Entry  me = (Map.Entry)it.next();

System.out.println(me.getKey()+"::::"+me.getValue());

}

    示例代码如下所示:

package ustc.maxiaolun.map;

 

import java.util.Collection;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

 

public class MapDemo2 {

 

public static void main(String[] args) {

/*

 * 取出Map中所有的元素。 map存储姓名---归属地。

 */

Map<String, String> map = new HashMap<String, String>();

 

map.put("xiaoqiang", "beijing");

map.put("wangcai", "funiushan");

map.put("daniu", "heifengzhai");

map.put("erhu", "wohudong");

map.put("zhizunbao", "funiushan");

 

//System.out.println(map.get("wangcai"));

 

/*

//演示keySet(); 取出所有的键,并存储到Set集合中。

Set<String> keySet = map.keySet();

 

//Map集合没有迭代器。但是可以将Map集合转成Set集合,在使用迭代器就ok了。

for (Iterator<String> it = keySet.iterator(); it.hasNext();) {

 

String key = it.next();

String value = map.get(key);

System.out.println(key+":"+value);

 

}

 

//演示entrySet(); Map.Entry:其实就是一个Map接口中的内部接口。

Set<Map.Entry<String, String>> entrySet = map.entrySet();

 

for (Iterator<Map.Entry<String, String>> it = entrySet.iterator(); it.hasNext();) {

Map.Entry<String, String> me = it.next();

String key = me.getKey();

String value = me.getValue();

System.out.println(key+"::"+value);

}

 */

 

//演示values(); 获取所有的值。

Collection<String> values = map.values();

 

for (Iterator<String> it = values.iterator(); it.hasNext();) {

String value = it.next();

System.out.println(value);

}

}

}

//原理

interface MyMap{//-->键值对

 

//entry就是map接口中的内部接口。

public static interface MyEntry{//-->键值对的映射关系

 

}

}

class MyDemo implements MyMap.MyEntry{

 

}

     什么时候使用Map集合呢?

    当需求中出现映射关系时,应该最先想到map集合。

 

    举例,获取星期几,代码如下:

 

package ustc.maxiaolun.map;

 

import java.util.HashMap;

import java.util.Map;

 

import ustc.maxiaolun.exception.NoWeekException;

 

public class MapTest {

 

public static void main(String[] args) {

/*

 * 什么时候使用map集合呢?

 * 当需求中出现映射关系时,应该最先想到map集合。

 */

String cnWeek = getCnWeek(3);

System.out.println(cnWeek);

String enWeek = getEnWeek(cnWeek);

System.out.println(enWeek);

}

 

/*

 * 根据中文的星期,获取对应的英文星期。

 * 中文与英文相对应,可以建立表,没有有序的编号,只能通过map集合。

 */

public static String getEnWeek(String cnWeek){

//创建一个表。

Map<String,String> map = new HashMap<String, String>();

map.put("星期一","Monday");

map.put("星期二","Tuesday");

map.put("星期三","Wednesday");

map.put("星期四","Thursday");

map.put("星期五","Friday");

map.put("星期六","Saturday");

map.put("星期日","Sunday");

return map.get(cnWeek);

}

 

/*

 * 根据用户指定的数据获取对应的星期。

 */

public static String getCnWeek(int num){

if (num>7 || num<=0)

throw new NotWeekException(num+", 没有对应的星期");

String[] cnWeeks = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};

return cnWeeks[num];

}

}

    程序中用到的NotWeekException异常代码如下:

 

package ustc.maxiaolun.exception;

 

public class NotWeekException extends RuntimeException {

 

/**

 *

 */

private static final long serialVersionUID = 1L;

 

public NotWeekException() {

super();

}

 

public NotWeekException(String message, Throwable cause,

boolean enableSuppression, boolean writableStackTrace) {

super(message, cause, enableSuppression, writableStackTrace);

}

 

public NotWeekException(String message, Throwable cause) {

super(message, cause);

}

 

public NotWeekException(String message) {

super(message);

}

 

public NotWeekException(Throwable cause) {

super(cause);

}

 

}

HashMap<K, V>类

    练习1 员工对象(姓名,年龄)都有对应的归属地, 将员工和归属存储到HashMap集合中并取出。同姓名同年龄视为同一个员工。

 

package ustc.maxiaolun.domain;

 

public class Employee implements Comparable<Employee>{

private String name;

private int age;

public Employee() {

super();

}

public Employee(String name, int age) {

super();

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return "Employee [name=" + name + ", age=" + age + "]";

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + age;

result = prime * result + ((name == null) ? 0 : name.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

Employee other = (Employee) obj;

if (age != other.age)

return false;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

return true;

}

@Override

public int compareTo(Employee o) {

int temp = this.age-o.age;

return temp==0?this.name.compareTo(o.name):temp;

}

}

package ustc.maxiaolun.map;

 

import java.util.HashMap;

import java.util.Map;

 

import ustc.maxiaolun.domain.Employee;

 

public class HashMapTest {

 

public static void main(String[] args) {

/*

 * 练习:

 * 员工对象(姓名,年龄)都有对应的归属地。

 * key=Employee  value=String

 *

 * 1.

 * 将员工和归属存储到HashMap集合中并取出。

 * 同姓名同年龄视为同一个员工。

 *

 */

Map<Employee,String> map = new HashMap<Employee,String>();//如果改成LinkedHashMap可以实现有序。

 

map.put(new Employee("xiaozhang",24),"北京");

map.put(new Employee("laoli",34),"上海");

map.put(new Employee("mingming",26),"南京");

map.put(new Employee("xili",30),"广州");

map.put(new Employee("laoli",34),"铁岭");//上海被覆盖掉了

 

for (Employee employee : map.keySet()) {

System.out.println(employee.getName()+":"+employee.getAge()+"..."+map.get(employee));

}

}

}

TreeMap<K, V>类

    练习2:接着上例,按照员工的年龄进行升序排序并取出。-->Comparable。再按照员工的姓名进行升序排序并取出。-->Comparator

 

package ustc.maxiaolun.map;

 

import java.util.Comparator;

import java.util.Map;

import java.util.TreeMap;

 

import ustc.maxiaolun.domain.Employee;

 

public class TreeMapTest {

 

public static void main(String[] args) {

/*

 * 练习:

 * 2.

 * 按照员工的年龄进行升序排序并取出。-->Comparable

 * 按照员工的姓名进行升序排序并取出。-->Comparator

 */

 

Comparator<Employee> comparator = new Comparator<Employee>(){

 

@Override

public int compare(Employee o1, Employee o2) {

int temp = o1.getName().compareTo(o2.getName());

return temp==0?o1.getAge()-o2.getAge():temp;

}

};

 

//Map<Employee,String> map = new TreeMap<Employee,String>();// 按照年龄

Map<Employee,String> map = new TreeMap<Employee,String>(comparator);//按照姓名

 

map.put(new Employee("xiaozhang",24),"北京");

map.put(new Employee("laoli",34),"上海");

map.put(new Employee("mingming",26),"南京");

map.put(new Employee("xili",30),"广州");

map.put(new Employee("laoli",34),"铁岭");

 

for(Map.Entry<Employee, String> me : map.entrySet()){

System.out.println(me.getKey().getName()+"::"+me.getKey().getAge()+"..."+me.getValue());

}

}

}

     Map查表法练习:

    "bwa-er+b+c=tyx_bac?ecrtdcvr" 获取字符串中每一个字母出现的次数。要求结果格式:a(2)b(1)d(3)...

 

    思路:

 

    1.获取到字母。

    2.如何获取字母次数?

        发现字母和次数有对应关系。而且对应关系的一方具备唯一性。就想到了Map集合。map集合就是一张表。

    3.使用查表法就可以了。

        先查第一个字母在表中的次数。如果次数不存在,说明是第一次出现,将该字母和1存储到表中。以此类推。当要查的次数存在,将次数取出并自增后,再和对应的字母存储到到表中,map表的特点是相同键,值覆盖!

    4.查完每一个字母后,表中存储的就是每一个字母出现的次数。

 

package ustc.maxiaolun.test;

 

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import java.util.TreeMap;

 

public class Test {

 

public static void main(String[] args) {

/*

 * 作业:"bwa-er+b+c=tyx_bac?ecrtdcvr"

 * 获取字符串中每一个字母出现的次数。要求结果格式:a(2)b(1)d(3)...

 * 思路:

 * 1.获取到字母。

 * 2.如何获取字母次数?

 * 发现字母和次数有对应关系。而且对应关系的一方具备唯一性。

 * 就想到了Map集合。map集合就是一张表。

 * 3.使用查表法就可以了。

 * 先查第一个字母在表中的次数。如果次数不存在,说明是第一次出现,将该字母和1存储到表中。

 * 以此类推。当要查的次数存在,将次数取出并自增后,再和对应的字母存储到到表中,map表的特点是相同键,值覆盖!

 * 4.查完每一个字母后,表中存储的就是每一个字母出现的次数。

 */

String str = "bwa-er+b+c=tyx_bac?ecrtdcvr";

String char_count = getCharCount(str);

System.out.println(char_count);

}

 

public static String getCharCount(String str) {

//1.将字符串转成字符数组。

char[] chs = str.toCharArray();

 

//2.定义map集合表。

Map<Character, Integer> map = new TreeMap<Character, Integer>();

 

//3.遍历字符数组。获取每一个字母。

for (int i = 0; i < chs.length; i++) {

//只对字母操作。

//if(!(chs[i]>='a'&&chs[i]<='z' || chs[i]>='A'&&chs[i]<='Z'))

if(!(Character.isLowerCase(chs[i]) || Character.isUpperCase(chs[i])))

continue;

//将遍历到的字母作为键去查表。获取值。

Integer value = map.get(chs[i]);

int count = 0;//用于记录次数

//如果次数存在,就用count记录该次数。如果次数不存在,就不记录,只对count自增变成1

if(value != null){

count = value;

}

count++;

map.put(chs[i],count);

/*

if(value == null){

map.put(chs[i],1);

}else{

value++;

map.put(chs[i],value);

}*/

}

return mapToString(map);

}

/*

 * 将map集合中的元素转成指定格式的字符串。a(2)b(1)d(3)......

 */

private static String mapToString(Map<Character, Integer> map) {

//1.数据多,无论类型是什么,最终都要变成字符串。所以可以使用StringBuilder

StringBuilder sb = new StringBuilder();

 

//2.遍历集合mapkeySet()

for(Character key : map.keySet()){

Integer value = map.get(key);

sb.append(key+"("+value+")");

}

/*

Set<Character> keySet = map.keySet();

for (Iterator<Character> it = keySet.iterator(); it.hasNext();) {

Character key = it.next();

Integer value = map.get(key);

//将键值存储到sb中。

sb.append(key+"("+value+")");

}*/

return sb.toString();

}

}

集合框架的工具类

Collections类

 

    java.util.Collections类的出现给集合操作提供了更多的功能。这个类不需要创建对象,完全由在 collection 上进行操作或返回 collection 的静态方法组成。

 

    1.对List排序:

         sort(list);//具备泛型限定,保证安全。

 

    2.逆序:

         reverseOrder

    3.最值:

         max

         min

    4.二分查找:

         binarySearch

 

    5.将非同步集合转成同步集合:

         synchronizedCollection

         synchronizedList

         SynchronizedSet

         synchronizedMa

 

    上述部分功能的解释:

 

    1.排序方法上的泛型的由来:

 

interface Comparable<T>

{

void compareTo(T o);

}

 

class Student extends Person implements Comparable<Person>

{

public int compareTo(Person p){//Person可以接受Student类型。

 

}

}

 

public static <T extends Comparable<? super T>> void sort(List<T> list)//直接定义泛型T,在编译时期就保证类型的正确。

{

//<T extends Comparable>:必须是Comparable的子类才具备比较功能。

//<? super T>:只要是T的父类,都可以接受T类型,进行比较。

}

 

public static void sort(List<Object> list)//老版本,即使编译通过,运行时期不安全,容易出现类型转换异常。

{

stu1.compareTo(stu2);

}

    2.模拟一个Collectionsmin()方法。

/*

 * 模拟一个获取字符串集合最大值的功能。

 */

public static String getMax(Collection<String> coll){

Iterator<String> it = coll.iterator();

 

//定义变量记录容器中其中一个。

String max = it.next();

 

//遍历容器所有的元素。

while(it.hasNext()){

String temp = it.next();

//在遍历过程中进行比较。只要比变量中的值大。用变量记录下来,就哦了。

if(temp.compareTo(max)>0){

max = temp;

}

}

return max;

}

/*

 * 模拟一个Collectionsmin方法。

 */

public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {

       Iterator<? extends T> i = coll.iterator();

       T candidate = i.next();

        while (i.hasNext()) {

           T next = i.next();

           if (next.compareTo(candidate) < 0)

               candidate = next;

       }

       return candidate;

}

   3.将非同步集合转成同步集合的原理:定义一个类,将非同步集合所有的方法加同一把锁后返回。

List list = new ArrayList();//非同步的。

 

list = MyCollections.synList(list);//返回一个同步的list

 

class MyCollections{

public static List synList(List list){

return new MyList(list);

}

private class MyList{

private List list;

private static final Object lock = new Object();

MyList(List list){

this.list = list;

}

public boolean add(Object obj){

synchronized(lock){

return list.add(obj);

}

}

public boolean remove(Object obj){

synchronized(lock){

return list.remove(obj);

}

}

}

}

    Collections工具类代码示例:

 

package ustc.maxiaolun.collections;

 

import java.util.ArrayList;

import java.util.Collection;

import java.util.Collections;

import java.util.Iterator;

import java.util.List;

 

import ustc.maxiaolun.comparator.ComparatorByLength;

 

public class CollectionsDemo {

 

public static void main(String[] args) {

/*

 * Collections排序、逆序、最值、同步方法演示

 */

methodDemo1();

 

Collection<String> coll = new ArrayList<String>();

coll.add("abcd");

coll.add("ab");

coll.add("haha");

coll.add("zzz");

String max = getMax(coll);

String max1 = Collections.max(coll,new ComparatorByLength());

System.out.println("max = "+max);

System.out.println("max1 = "+max1);

 

/*

 * Collections中有一个可以将非同步集合转成同步集合的方法。

 * 同步集合  synchronized集合(非同步集合);

 */

Collection<String> synColl = Collections.synchronizedCollection(coll);

}

 

public static void methodDemo1() {

List<String> list = new ArrayList<String>();

list.add("abc");

list.add("xy");

list.add("haha");

list.add("nba");

System.out.println(list);

 

//对list排序。自然排序。使用的是元素的compareTo方法。

Collections.sort(list);

System.out.println(list);

 

//按照长度排序。

Collections.sort(list,new ComparatorByLength());

System.out.println(list);

 

//按照长度逆序。

Collections.sort(list,Collections.reverseOrder(new ComparatorByLength()));//reverseOrder强行逆转比较器顺序。

System.out.println(list);

}

}

    代码中用到的比较器实现如下:

package ustc.maxiaolun.comparator;

 

import java.util.Comparator;

 

public class ComparatorByLength implements Comparator<String> {

@Override

public int compare(String o1, String o2) {

int temp = o1.length()-o2.length();

return temp==0?o1.compareTo(o2):temp;

}

}

    Collection 和 Collections的区别:

 

    Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。

 

    Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有SetList,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。

 

Arrays类

 

    java.util.Arrays类是用来操作数组的工具类,里面的方法都是静态的。代码示例:

 

package ustc.maxiaolun.arrays;

 

import java.util.Arrays;

 

public class ArraysDemo {

 

public static void main(String[] args) {

//int[] arr = new int[3];

Integer[] arr = new Integer[3];

String[] arr1 = new String[3];

swap(arr,1,2);

swap(arr1,1,2);

 

int[] arr2 = {45,1,23,56,67};

System.out.println(arr2);//[I@1db9742

System.out.println(Arrays.toString(arr2));//[45, 1, 23, 56, 67],底层用的是StringBuilder

}

 

public static <T> void swap(T[] arr, int x, int y){//T必须是引用类型。int--->Integer,自动装箱拆箱。

T temp = arr[x];

arr[x] = arr[y];

arr[y] = temp;

}

 

//toString的源码实现。

public static String toString(int[] a) {

        if (a == null)

            return "null";

        int iMax = a.length - 1;

        if (iMax == -1)

            return "[]";

 

        StringBuilder b = new StringBuilder();

        b.append('[');

        for (int i = 0; ; i++) {//中间省略条件判断,提高了效率。

            b.append(a[i]);

            if (i == iMax)

                return b.append(']').toString();

            b.append(", ");

        }

    }

}

     Arrays类中有一个很重要的方法就是asList()方法,它返回一个受指定数组支持的固定大小的List列表。所以这里我就重点说一下,如何实现数组和集合之间的转换。

    1.数组转成集合

 

    Arrays.asList方法:将数组转换成list集合。

 

<span style="font-size:14px;">String[] arr = {"abc","kk","qq"};

List<String> list = Arrays.asList(arr);//将arr数组转成list集合。</span>

    将数组转换成集合,有什么好处呢?

    用aslist方法,将数组变成集合;可以通过list集合中的方法来操作数组中的元素:isEmpty()containsindexOfset等方法。

 

    注意(局限性):

 

    数组是固定长度,不可以使用集合对象增加或者删除等,会改变数组长度的功能方法。比如addremoveclear。(会报不支持操作异常UnsupportedOperationException)。

 

    如果数组中存储的引用数据类型,直接作为集合的元素可以直接用集合方法操作。

 

    如果数组中存储的是基本数据类型,asList会将数组实体作为集合元素存在。

 

package ustc.maxiaolun.arrays;

 

import java.util.Arrays;

import java.util.List;

 

public class ArraysDemo2 {

 

public static void main(String[] args) {

/*

 * 数组转成集合。

 *

 * Arrays:用来操作数组的工具类,里面的方法都是静态的。

 */

demo_1();

demo_2();

}

 

public static void demo_1() {

/*

 * 重点:Arrays asList(数组将数组转成集合。

 *

 * 为什么要把数组转成集合?

 * 因为数组能用的方法是有限的:折半、排序、toStringequalsfill,没了。

 * 我想知道数组的位置、是否包含某个元素,这些都没有,但是集合中有这些方法。

 *

 * 好处:数组转成List集合,就是为了使用集合的方法操作数组中的元素。

 *

 * 注意:数组的长度是固定的,所以对于集合的增删方法是不可以使用的,

 * 否则会发生UnsupportedOperationException

 */

String[] strs = {"abc","haha","nba","zz"};

 

//以前的做法:自己定义一个函数实现功能

boolean b = myContains(strs, "nba");

System.out.println("contains:"+b);

 

//现在的做法:数组转成集合,从而利用集合的方法

List<String> list = Arrays.asList(strs);

System.out.println("list contains:"+list.contains("nba"));

System.out.println(list);

 

//list.add("qq");//报错--> java.lang.UnsupportedOperationException

//因为数组是固定长度的。

}

 

/*

 * 自定义 对数组中某元素进行查找。

 */

public static boolean myContains(String[] arr, String key){

for (int i = 0; i < arr.length; i++) {

String str = arr[i];

if(str.equals(key))

return true;

}

return false;

}

 

public static void demo_2() {

/*

 * 如果数组中都是引用数据类型,转成集合时,数组元素直接作为集合元素。

 * 如果数组中都是基本数据类型,会将数组对象作为集合中的元素。(因为集合中只能存对象)

 */

 

int[] arr = {45,23,78,11,99};

List<int[]> list = Arrays.asList(arr);

System.out.println(list);//[[I@1db9742]

System.out.println(list.size());//1

System.out.println(list.get(0));//[I@1db9742

//原因:把数组作为元素,存进了集合中。

 

//那上面代码的泛型该咋写?

//泛型应该是集合中元素的类型。arrint[]类型,所以是List<int[]> list

//实际中,我们应该声明为Integer数组,而不是int数组,如下:

 

Integer[] arr1 = {45,23,78,11,99};

List<Integer> list1 = Arrays.asList(arr1);

System.out.println(list1);//[45, 23, 78, 11, 99]

System.out.println(list1.get(0));//45

}

}

    2.集合转成数组

 

    用的是Collection接口中的方法:toArray()

 

    注意:

 

    如果给toArray传递的指定类型的数据长度小于了集合的size,那么toArray方法,会自定再创建一个该类型的数据,长度为集合的size

    如果传递的指定的类型的数组的长度大于了集合的size,那么toArray方法,就不会创建新数组,直接使用该数组即可,并将集合中的元素存储到数组中,其他为存储元素的位置默认值null

    所以,在传递指定类型数组时,最好的方式就是指定的长度和size相等的数组。

 

    将集合变成数组后有什么好处?

    限定了对集合中的元素进行增删操作,只要获取这些元素即可。

 

package ustc.maxiaolun.arrays;

 

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

 

public class ArraysDemo3 {

 

public static void main(String[] args) {

/*

 * 集合转成数组。

 *

 * 使用的就是Collection接口中的toArray方法。

 *

 * 为什么要把集合转成数组?

 * 可以对集合中的元素操作的方法进行限定,不允许对其进行增删。

 */

List<String> list = new ArrayList<String>();

list.add("abc");

list.add("haha");

 

/*

 * toArray方法需要传入一个指定类型的数组。

 * 长度该如何定义呢?

 * 传入的数组长度,如果小于集合长度,那么该方法会创建一个同类型并和集合相同size的数组。

 * 传入的数组长度,如果大于集合长度,那么该方法会使用指定的数组,存储集合中的元素,其他位置默认为null

 *

 * 所以建议,长度就指定为集合的size();

 */

String[] arr =list.toArray(new String[0]);

System.out.println(Arrays.toString(arr));//[abc, haha]

 

String[] arr1 =list.toArray(new String[3]);

System.out.println(Arrays.toString(arr1));//[abc, haha, null]

 

String[] arr2 =list.toArray(new String[list.size()]);

System.out.println(Arrays.toString(arr2));//[abc, haha]

}

}

可变参数(...)

    JDK1.5出现的技术,用到函数的参数上,当要操作的同一个类型元素个数不确定的时候,可是用这个方式,这个参数可以接受任意个数的同一类型的数据。

 

    以前我们计算元素之和,用的是下面的方法,针对不同个数,要定义多个函数。

 

public static int add(int i, int j, int k) {

 

return i + j + k;

}

 

public static int add(int i, int j) {

 

return i + j;

}

    之后,我们转而为计算数组元素之和,如下所示。

public static int add(int[] arr) {

int sum = 0;

for (int i = 0; i < arr.length; i++) {

sum += arr[i];

}

return sum;

}

    但是问题是,数组的长度是固定的,如果不同需求中,个数不一样,那么要用不同容量的数组先去存起来,比较麻烦。

 

    和以前接收数组不一样的是:以前定义数组类型,需要先创建一个数组对象,再将这个数组对象作为参数传递给函数。

 

    现在,直接将数组中的元素作为参数传递即可。底层其实是将这些元素进行数组的封装,而这个封装动作,是在底层完成的,被隐藏了。所以简化了用户的书写,少了调用者定义数组的动作。

 

    注意:

    如果在参数列表中使用了可变参数,可变参数必须定义在参数列表结尾(也就是必须是最后一个参数,否则编译会失败)

    如果要获取多个int数的和呢?可以使用将多个int数封装到数组中,直接对数组求和即可。

 

package ustc.maxiaolun.param;

 

public class ParamDemo {

 

public static void main(String[] args) {

 

int sum = add(4, 5);

int sum1 = add(4, 5, 6);

 

/*

 * 计算多个整数的和。

 */

int[] arr = {34,1,4,6};

int[] arr2 = {23,35,45,6,57,6};

int sum2 = add(arr);

int sum3 = add(arr2);

 

/*

 * JDK 1.5 可变参数,不用定义数组了。编译后的class文件中自动带着数组。

 * 注意事项:只能定义在参数列表的最后。

 * public static int add1(int x, int... arr) --> right

 * public static int add1(int... arr, int x) --> wrong

 */

int sum4 = add1(34,1,4,6,57,9);

int sum5 = add1(99,11,24,56);

}

public static int add1(int... arr){

int sum = 0;

for (int i = 0; i < arr.length; i++) {

sum += arr[i];

}

return sum;

}

 

public static int add(int[] arr) {

int sum = 0;

for (int i = 0; i < arr.length; i++) {

sum += arr[i];

}

return sum;

}

 

public static int add(int i, int j, int k) {

 

return i + j + k;

}

 

public static int add(int i, int j) {

 

return i + j;

}

}

静态导入

    导入了类中的所有静态成员,简化静态成员的书写。例如:import static java.util.Collections.*; -->导入了Collections类中的所有静态成员。但如果同名了,还是要加上各自的包名的。

 

package ustc.maxiaolun.staticimport;

 

import static java.util.Collections.*;

 

import static java.lang.System.*;

 

public class StaticImportDemo {

 

public static void main(String[] args) {

/*

 * 静态导入。

 */

java.util.List<String> list = new java.util.ArrayList<String>();

list.add("a");

list.add("c");

 

sort(list);

System.out.println(max(list));

 

out.println("hello");

}

}

模拟斗地主

 

    1.首先模拟一下QQ斗地主的洗牌和发牌:

 

 

package ustc.maxiaolun.poker;

 

import java.util.ArrayList;

import java.util.Collections;

 

/*

 * 模拟斗地主洗牌和发牌

 *

 * 分析:

 * A:创建一个牌盒

 * B:装牌

 * C:洗牌

 * D:发牌

 * E:看牌

 */

 

public class PokerDemo {

 

public static void main(String[] args) {

//创建一个牌盒

ArrayList<String> array = new ArrayList<String>();

 

//装牌

//黑桃A,黑桃2,黑桃3...,黑桃k

//红桃A...

//梅花A...

//方块A...

//定义一个花色数组

String[] colors = {"","","",""};

//定义一个点数数组

String[] numbers = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};

//装牌

for(String color : colors){

for(String number : numbers){

array.add(color.concat(number));

}

}

array.add("小王 ");

array.add("大王 ");

 

//洗牌

Collections.shuffle(array);

 

//发牌

ArrayList<String> fengQingYang = new ArrayList<String>();

ArrayList<String> linQingXia = new ArrayList<String>();

ArrayList<String> maxiaolun = new ArrayList<String>();

ArrayList<String> diPai = new ArrayList<String>();

 

for (int i = 0; i < array.size(); i++) {

if(i >= array.size() - 3){

diPai.add(array.get(i));

}else if(i % 3 == 0){

fengQingYang.add(array.get(i));

}else if(i % 3 == 1){

linQingXia.add(array.get(i));

}else{

maxiaolun.add(array.get(i));

}

}

 

//看牌

lookPoker("风清扬",fengQingYang);

lookPoker("林青霞",linQingXia);

lookPoker("马小伦",maxiaolun);

 

lookPoker("底牌",diPai);

}

 

public static void lookPoker(String name, ArrayList<String> array) {

System.out.print(name + "的牌是:");

for(String s : array){

System.out.print(s + " ");

}

System.out.println();

}

}

    运行结果如下:

 

 

    2.根据上述程序运行结果,我们得考虑发到手里的牌进行排序,这样看起来比较舒服。这里有一个要求,需要尽可能多的使用到本篇博文前面的知识点。所以,做了如下的分析:

 

 

    3.针对上述分析,最终实现了模拟斗地主洗牌发牌、并对手牌进行排序的案例。代码如下:

 

package ustc.maxiaolun.poker;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.HashMap;

import java.util.TreeSet;

 

/*

 * 思路:

 * A:创建一个HashMap集合

 * B:创建一个ArrayList集合

 * C:创建花色数组和点数数组

 * D:0开始往HashMap里面存储编号,并存储对应的牌

 *                  同时往ArrayList里面存储编号即可。

 * E:洗牌(洗的是编号)

 * F:发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收)

 * G:看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)

 */

 

public class PokerDemo2 {

 

public static void main(String[] args) {

//创建一个HashMap集合

HashMap<Integer, String> hm = new HashMap<Integer, String>();

 

//创建一个ArrayList集合

ArrayList<Integer> array = new ArrayList<Integer>();

 

//创建花色数组和点数数组

//定义一个花色数组

String[] colors = {"","","",""};

//定义一个点数数组

String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};

 

//从0开始往HashMap里面存储编号,并存储对应的牌,同时往ArrayList里面存储编号即可。

int index = 0;

for(String number : numbers){

for(String color : colors){

String poker = color.concat(number);

hm.put(index, poker);

array.add(index);

index++;

}

}

hm.put(index, "小王");

array.add(index++);

hm.put(index, "大王");

array.add(index);

 

//洗牌(洗的是编号)

Collections.shuffle(array);

 

//发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收)

TreeSet<Integer> fengQingYang = new TreeSet<Integer>();

TreeSet<Integer> linQingXia = new TreeSet<Integer>();

TreeSet<Integer> maxiaolun = new TreeSet<Integer>();

TreeSet<Integer> diPai = new TreeSet<Integer>();

 

for(int i = 0; i < array.size(); i++){

if(i >= array.size()-3){

diPai.add(array.get(i));

}else if(i % 3 == 0){

fengQingYang.add(array.get(i));

}else if(i % 3 == 1){

linQingXia.add(array.get(i));

}else{

maxiaolun.add(array.get(i));

}

}

 

//看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)

lookPoker("风清扬", fengQingYang, hm);

lookPoker("林青霞", linQingXia, hm);

lookPoker("马小伦", maxiaolun, hm);

lookPoker("底牌", diPai, hm);

 

 

}

//写看牌的功能

public static void lookPoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm){

System.out.print(name + "的牌是:");

for(Integer key : ts){

String value = hm.get(key);

System.out.print(value + " ");

}

System.out.println();

}

}

程序运行结果如下:

 

 


 

…………………未完待续………………

 

更多内容尽在:www.njzhenghou.com

咨询热线
预约试听:025-86665061
官方公众号:ZhenghouSoft
技术热线:025-86665061
联系地址
南京总部:南京市鼓楼区湖南路16号5楼
重庆中心:重庆市渝中区投资大厦6楼
武汉中心:江夏区光谷智慧园16栋
微信公众号
联系我们
咨询热线:025-86665061
友情链接
Copyright © 2018 南京|重庆|武汉 专注软件测试培训、ISTQB考证、项目合作、Java开发-正厚软件官网,值得信赖 苏ICP备17057415号