本文主要是介绍10.集合框架(三)【Map】【集合技巧】【工具类Collections】【工具类Arrays】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、Map集合(接口)
1. 概述
Map集合每次都是一次添加一对元素。Collection是每次添加一个元素。所以,Map集合也称为双列集合,Collection集合也称为单列集合。其实,Map集合中存储的是键值对。
Map集合中必须保证键的唯一性。一个映射不能包含重复的键,每个键最多只能映射到一个值。
在有映射关系时,可以优先考虑使用Map。
2. Map集合常用方法
1)添加
value put(key,value):返回前一个和key关联的值,如果之前没有关联的值,返回
null。
2)删除
void clear():清空map集合。
valueremove(key):根据指定的key删除此键值对,并返回和key关联的值。
3)判断
boolean constainsKey(key)
boolean constainsValue(Value)
boolean isEmpty()
4)获取
Value get(key):通过键获取值,如果没有该键,则返回null.
可以通过返回null,判断是否含有指定键。
int size():返回此映射中的键值对个数。
keyset():返回此映射中包含键的Set集合。
entrySet():返回此映射中包含的映射关系的Set集合。
Collection values():返回Map集合的所有值得Collection集合。
例子:Collection values()方法演示
<span style="font-size:18px">import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;public class ValuesDemo {public static void main(String[] args) {//创建集合Map<Integer,String> map = new HashMap();//调用处理方法。method(map);}public static void method(Map<Integer,String> map){//添加元素map.put(8, "lisi");map.put(2, "wangwu");map.put(4, "zhangsan");map.put(7, "zhaoliu");//调用values方法Collection<String> values = map.values();Iterator<String> it = values.iterator();while(it.hasNext()){System.out.println(it.next());}}
}
</span>
3. Map集合常用的子类
Map
|--HashTable:数据结构为哈希表。是同步的,不允许null作为键和值。
|--Properties:用来存储键值对的配置文件的信息。可以和IO技术相结合。
|--HashMap:内部结构是哈希表,不同步,允许null作为键和值。
|--TreeMap:内部结构是二叉树,不同步。
4. 如何迭代获取Map集合中的元素?
获取Map集合元素的原理:Map集合是没有迭代器的,Collection才有迭代器。
所以需要将Map转为Set集合。之所以转成Set,是因为Set具备唯一性,和Map
集合的键的唯一性相符合。其实Set底层就是用Map的方法。
如何将Map转为Set?
1)通过keySet方法获取Map集合所有键的Set集合。迭代获取每一个键,再调用
get方法获取每一个键相应的值即可
<span style="font-size:18px">import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;public class keySetDemo {/**keySet()用于获得map中所有的键。可以用它来输出每个键对应的值。* @param args*/public static void main(String[] args) {//创建集合Map<Integer,String> map = new HashMap();//调用处理方法。method(map);}/**方法功能:取出map中所有的元素。* 原理:通过keySet方法获取map中所有键所在的Set集合。* 通过Set中的迭代器获取每一个键。* 再通过get方法对每一个键获取相应的值即可。* @param map*/public static void method(Map<Integer,String> map){//添加元素map.put(8, "lisi");map.put(2, "wangwu");map.put(4, "zhangsan");map.put(7, "zhaoliu");//调用keySet方法,获取map中所有的键。Set<Integer> keyset = map.keySet();//调用Set中的迭代器,根据每一个键获取相关联的值Iterator<Integer> it = keyset.iterator();while(it.hasNext()){//获取键Integer key = it.next();//根据键获取值。String value = map.get(key);//打印键值对。System.out.println(key+":"+value);}}
}
</span>
2)通过entrySet方法获取获取所有键值的映射关系的Set集合,这个映射关系的类型是Map.Entry.迭代获取每一个映射关系,调用getKey、getValue方法分别获取每一个映射关系的键和值。
<span style="font-size:18px">import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;public class entrySetDemo {public static void main(String[] args) {//创建集合Map<Integer,String> map = new HashMap();//调用处理方法。method(map);}public static void method(Map<Integer,String> map){//添加元素map.put(8, "lisi");map.put(2, "wangwu");map.put(4, "zhangsan");map.put(7, "zhaoliu");/** 通过map转成set就可以迭代。* 找到了另一个方法:entrySet方法。* 该方法将键和值得映射关系作为对象存储到了Set集合中。* 这个映射关系的类型就是Map。Entry类型(结婚证)。*/Set<Map.Entry<Integer, String>> entrySet = map.entrySet();Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();while(it.hasNext()){Map.Entry<Integer, String> me = it.next();Integer key = me.getKey();String value = me.getValue();System.out.println(key+":"+value);}}
}
</span>
5. Map练习
1)"fagavacbsacdfa"获取该字符串中,每个字母出现的次数。
要求打印结果是:a(2)b(1)...;
代码实现
<span style="font-size:18px">import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;/** 思路:* 对于结果的分析发现,字母和字数之间存在着映射关系,而且这种关系很多。* 很多就需要存储,能存储映射关系的容器有数组和Map集合。* 关系一方是有序编号吗?没有!* 所以可以用TreeMap。* * 这个集合最终存储的应该是字母和次数的映射关系。* * 1.因为操作的是字符串中的字母,所以先将字符串变成字符数组。* 2.遍历字符数组,用每一个字母作为键去查Map这个表。* 如果该字母不存在,就将该字母作为键,1为值存储到Map表中。* 如果该字母存在,就将该字母对应的值取出并+1,再将该字母和+1后的值存储到Map集合中。* 键相同值会覆盖。这样就实现记录字母出现的次数。* 3.遍历结束,map集合就记录所有字母出现的次数。上*/public class MapTest {public static void main(String[] args) {String str = "fa+g-avacAbsad gfacDdfa";String s = getChar(str);System.out.println(s);}public static String getChar(String str) {//将字符串变成字符数组。char[] chs = str.toCharArray();//定义map集合表。Map<Character,Integer> map = new TreeMap<Character,Integer>();//遍历数组for (int i = 0; i < chs.length; i++) {//筛选,只统计字母if(!(chs[i]>='a' && chs[i]<='z' ||chs[i]>='A' && chs[i]<='Z')){continue;}//查表。Integer value = map.get(chs[i]);Integer count = 1;//判断值是否为null.if(value!=null){count = value+1;}map.put(chs[i], count);/*if(value==null){map.put(chs[i], 1);}else{map.put(chs[i], value+1);}*/}return mapToString(map);}private static String mapToString(Map<Character, Integer> map) {//将结果变成字符串输出StringBuilder sb = new StringBuilder();Iterator<Character> it = map.keySet().iterator();while(it.hasNext()){Character key = it.next();Integer value = map.get(key);sb.append(key+"("+value+")");}return sb.toString();}
}
</span>
2)练习2:Map集合练习——查表法
代码实现
<span style="font-size:18px">import java.util.HashMap;
import java.util.Map;public class MapTest2 {public static void main(String[] args) {/** * 在查表法中的应用较为多见。*/String week = getWeek(5);System.out.println(week);System.out.println(getWeekByMap(week));}private static String getWeekByMap(String week) {Map<String,String> map = new HashMap<String,String>();map.put("星期一", "Mons");map.put("星期二", "Tues");map.put("星期三", "wend");map.put("星期四", "thus");map.put("星期五", "Frid");map.put("星期六", "Sate");map.put("星期日", "Sund");map.put("星期天", "Sund");return map.get(week);}public static String getWeek(int i) {String[] week = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};return week[i];}
}
</span>
二、集合的一些技巧
1) 选择哪个集合?
需要唯一吗?
需要:Set
需要制定顺序:
需要:TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要唯一:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList
2) 如何记录每一个容器的数据结构和所属体系呢?
看名字!
List
|--ArrayList
|--linkedList
Set
|--HashSet
|--TreeSet
后缀名就是该集合所属体系。
前缀名就是该集合的数据结构。
看到array:就要想到数组,想到查询快,有角标。
看到link:就要想到链表,想到增删快,想到add,get,remove+firstlast方法。
看到hash:就要想到哈希表,就想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。
看到tree:就要想到二叉树,就想到排序,就要想到两个接口Comparable,Comparator.
而且通常这些常用的集合容器都是不同步的。
三、工具类Collections
1. 概述
Collections类是由在collection上操作或返回collection的静态方法组成。不需要创建对象。
2. 常见操作
1) 排序
void sort(List<T> list);根据自然顺序对集合中的元素进行排序。
void shuffle(List<?> list);使用默认随机源对List集合中的元素进行随机排序。
void sort(List<T>lsit,Comparator<? super T> c);根据指定比较器的排序方法对List集合进行排序。
2) 查找
T max(Collection<? extendsT> coll);根据集合的自然顺序,获取指定集合中的最大元素。
T max(Collection<?extends T> coll,Comparator<? super T> comp);根据指定比较器,获取集合的最大元素。
intbinarySearch(Lsit<?extends Comparable<? super T>> list,Tkey);二分法查法查找key。
3) 替换
void fill(List<? super T> list, T obj);将list集合中的所有元素替换为obj
booleanreplaceAll(List<T>lsit,T oldVal,T newVal);用newVal替换集合中的oldVal值.
voidswap(Listlist,int i,int j);/在指定列表的指定位置处交换元素.
4) 反转
reverse(List<?>list);//反转list集合中元素的顺序。
5) 同步的集合,将非同步的集合转换为同步的集合,就是加锁。
synchronizedCollection(Collection<T>c)
synchronizedList(List<T> List)
通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
给非同步的集合加锁的原理:
<span style="font-size:18px">List list = new ArrayList();//非同步的
list = MyCollections.synlist(list);//同步的class MyCollections{public List synlist(List list){return new MyList(list);}
}
class MyList implements List{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);}}
}
</span>
Collections类演示
<span style="font-size:18px">import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;import p2.comparator.ComparatorByLength;public class CollectionsDemo {public static void main(String[] args) {List<String> list = new ArrayList<String>();list.add("detasd");list.add("abc");list.add("detasd");list.add("cfd");list.add("zd");list.add("gtwd");// System.out.println(list);//对list集合进行指定顺序的排序。
// Collections.sort(list);
// System.out.println(list);// mySort(list);
// mySort(list,new ComparatorByLength());
// Collections.sort(list,new ComparatorByLength());
// System.out.println(list);// demo_2();demo_3();}/**其他方法:*1。fill(list,"cc");将集合中所有元素全部替换为cc.*2.shuffle(list);随机排序集合。 **3.将非同步的集合转换成同步的集合,就是加锁。* synchronizedCollection(Collection<T> c)* synchronizedList(List<T> List)*/ public static void demo_3() {List<String> list = new ArrayList<String>();list.add("detroit");list.add("abc");list.add("za");list.add("hfdc");System.out.println(list);//fill方法
// Collections.fill(list, "qnm");//shuffle方法Collections.shuffle(list);System.out.println(list);}/*** 替换* repalceAll(list,a,b);* fill(list,a),将集合中所有的元素替换为a。*/public static void demo_2() {List<String> list = new ArrayList<String>();list.add("detasd");list.add("abc");System.out.println(list);//替换Collections.replaceAll(list, "abc", "nba");/** 原理:* set(index,"nba");* index = indexOf("abc");* 整合起来:set(indexOf("abc","nba");*/System.out.println(list);}/*** Collections逆序和替换。*/public static void demo_1() {// TreeSet<String> ts = new TreeSet<String>(new Comparator<String>(){
//
// @Override
// public int compare(String o1, String o2) {
//
// int temp = o2.compareTo(o1);
// return temp;
// }// });/** 逆序:Collections.reverseOrcer();* 原理在上面注释部分。*/
// TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());//若调用比较器排序后再逆序。TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));ts.add("abc");ts.add("b");ts.add("tesd");ts.add("length");ts.add("nba");System.out.println(ts);}/*** Collections.binarySearch(list)演示* 折半和最值。*/public static void demo(){List<String> list = new ArrayList<String>();list.add("detasd");list.add("abc");list.add("detasd");list.add("cfd");list.add("zd");list.add("gtwd");// Collections.sort(list);
// System.out.println(list);// int index = Collections.binarySearch(list, "bde");//index=-2,负号表示没找到。插入位置index=2-1=1.
//
// System.out.println("index="+index);//获取最大值。
// String max = Collections.max(list);//获取长度最长的元素,调用比较器String max = Collections.max(list,new ComparatorByLength());System.out.println("max="+max);}/** sort(list,new ComparatorByLength());方法原理:*/public static <T > void mySort(List<T> list,Comparator<? super T> camp) {for (int i = 0; i < list.size()-1; i++) {for (int j = i+1; j < list.size(); j++) {if(camp.compare(list.get(j), list.get(j))>0){// T temp = list.get(i);
// list.set(i,list.get(j));
// list.set(j,temp);Collections.swap(list,i,j);}}}}/** sort(list)方法的原理:* 因为sort方法能接受任意泛型的list进行比较排序,所以mySort方法也要实现这个功能。* 方法中用到了compareTo方法,如果用通配符?,虽然能接受不同类型的泛型,但是通配符* 是Object类型的,Object里没有定义compareTo方法,* 所以只能定义泛型方法。并且该泛型必须具备比较性,要继承comparable才能调用compareTo方法。*/public static <T extends Comparable<? super T>> void mySort(List<T> list) {for (int i = 0; i < list.size()-1; i++) { for (int j = i+1; j < list.size(); j++) {if(list.get(i).compareTo(list.get(j))>0){/*T temp = list.get(i);list.set(i,list.get(j));list.set(j,temp);*///替代方法Collections.swap(list,i,j);} }} }
}
</span>
四、工具类Arrays
Arrays也是集合框架的工具类。里面全是静态方法。
1. 常见方法
List<T>asList(arr);将数组转换为集合。
注意:
1) 可以使用集合的方法来操作数组元素,弥补数组工具类中方法不多的
的不足。
数组的长度是固定的,所以数组转换成集合后不能增删。
即不能使用add()、remove()、clear()等改变长度的方法,否则会
发生UnsupportedOperationException异常。
2) 如果数组中的元素都是对象,变成集合时,数组中的元素直接转为集合中的元素
3) 如果数组中的元素都是基本数据类型,那么将该数组整体作为集合中的一个元素。
binarySearch();二分查找方法
sort();排序方法
fill();替换方法
String toString();接收各种数组类型参数,并返回指定数组内容的字符串表现形式。
toString()方法的实现原理:
<span style="font-size:18px">//toString 的经典实现public static String myToString(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(", ");}}
</span>
例子:
<span style="font-size:18px">import java.util.Arrays;
import java.util.List;public class ArraysDemo {public static void main(String[] args) {/** Arrays:集合框架的工具类。里面的方法都是静态的。*/int[] arr = {3,1,2,54,65,21};System.out.println(Arrays.toString(arr));//将数组变成字符串 demo_2(); }public static void demo_2() {/** 如果数组中的元素时对象,转成集合时,直接将数组中的元素作为集合的元素进行存储。* 如果数组中的元素是基本类型数值,转成集合时,会将该整个数组作为集合的元素进行存储。*/int[] arr = {31,21,47,56};List<int[]> list = Arrays.asList(arr);//将数组转成集合。System.out.println(list);}public static void demo_1() {/** 重点掌握:List asList(数组):将数组转成集合。* 好处:可以使用集合的方法操作数组元素,弥补数组工具类中方法不多的不足。* 注意:数组长度是固定的,所以数组转成集合后不能增删,* 即不能使用:add();remove();clear()等改变长度的方法。* 否则,会发生UnsupportedOperationException异常。* * */String[] arr = {"abc","haha","xixi"};boolean b = myContains(arr, "xixi");System.out.println("contains:"+b);//将数组转成集合。List<String> list = Arrays.asList(arr);boolean b1 = list.contains("xixi");System.out.println("list contains:"+b1);// list.add("hiahia");//UnsupportedOperationException,不能修改长度System.out.println(list);}public static boolean myContains(String[] arr,String key){for (int i = 0; i < arr.length; i++) {if (arr[i].equals(key)) {return true;}}return false;}
}
</span>
2. toArray——集合转成数组
集合转成数组,使用的是Collection接口的toArray方法。
1) 好处:
集合转成数组,可以对集合中的元素操作方法进行限定,不能增删。
建议:数组长度最好指定为集合的size.
2) toArray方法详细解读
toArray方法需要传入一个指定类型的数组。
该如何确定数组长度呢?
如果长度小于集合的size,那么该方法会创建一个同类且和集合相同size的数组。
如果长度大于集合的size,那么该方法会将集合中的元素存储到指定的
数组,多出的长度将默认为null。
例子:
<span style="font-size:18px">mport java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class ToArray {public static void main(String[] args) { List<String> list = new ArrayList<String>();list.add("abc1");list.add("abc2");list.add("abc3");String[] arr = list.toArray(new String[3]);//集合转成数组,需要指定数组。System.out.println(Arrays.toString(arr)); }
}
</span>
这篇关于10.集合框架(三)【Map】【集合技巧】【工具类Collections】【工具类Arrays】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!