首页 > 代码库 > java(八)集合
java(八)集合
Map
Map<K,V>:Map集合一次添加一对元素,Collection一次添加一个元素。
所以Map集合也称为双列集合,而Collection称为单列集合。
其实Map集合存储的就是键值对。
Map集合必须保证键的唯一性。
常用方法:1.添加:
value put(key,value):返回前一个和key关联的值,若没有则返回null。
2.删除:
void clear():清空map集合。
value remove():根据指定的key删除这个键值对。
3.判断
boolean containsKey(key);
boolean containsValue(Value);
boolean isEmpty();
4.获取
value get(Key):通过键获取值,若没有该键返回null。
也可以通过返回null来判断是否包含指定键。
int size();获取键值对个数。
常用方法演示:
package day18;
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap();
method(map);
}
public static void method(Map<Integer,String> map){ //学号和姓名
//添加元素
System.out.println(map.put(8, "wangcai"));//输出null
System.out.println(map.put(8, "xiaoqiang"));//输出wangcai 存相同键,值会覆盖
map.put(2, "zhangsan");
map.put(7, "zhaoliu");
System.out.println(map); //输出是无序的。
//删除元素
System.out.println("remove:"+map.remove(2));
System.out.println(map);
//判断
System.out.println("containsKey:"+map.containsKey(7));
//获取
System.out.println("get:"+map.get(6));
System.out.println(map);
}
}
输出结果为:
wangcai
{2=zhangsan, 7=zhaoliu, 8=xiaoqiang}
remove:zhangsan
{7=zhaoliu, 8=xiaoqiang}
containsKey:true
get:null
{7=zhaoliu, 8=xiaoqiang}
get方法一次只能取出一个元素,怎么能全部取出呢?(3种方法)
1.取出map中的所有元素原理:先通过KeySet方法获取map中所有的键所在的Set集合,
再通过Set的迭代器获取到每一个键,再对每一个键通过map的get方法获取其对应的值即可。
2.通过map转换成set就可以迭代,那么就找到了另一个方法entrySet。
该方法将键和值的映射关系作为作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型(结婚证)
3.如果只获取所有的value值,不需要获取键值,有一种简便的方法——values方法。
package day18;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapDemo {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap();
method_KeySet(map);
method_entrySet(map);
method_values(map);
}
public static void method_KeySet(Map<Integer,String> map){
map.put(8, "wangcai");
map.put(2, "zhangsan");
map.put(7, "zhaoliu");
map.put(6, "yaoming");
Set<Integer> KeySet=map.keySet();
Iterator <Integer> it=KeySet.iterator();
while(it.hasNext()){
Integer key=it.next();
String value=http://www.mamicode.com/map.get(key);
System.out.println(key+":"+value);
}
}
public static void method_entrySet(Map<Integer,String> map){
map.put(8, "wangcai");
map.put(2, "zhangsan");
map.put(7, "zhaoliu");
map.put(6, "yaoming");
Set<Map.Entry<Integer,String>> entrySet=map.entrySet();
Iterator<Map.Entry<Integer,String>> it=entrySet.iterator();
//Entry是Map接口中的内部接口,所以定义迭代器时要这么写,参考内部类。
while(it.hasNext()){
Map.Entry<Integer,String> me=it.next();
Integer key=me.getKey();
String value=http://www.mamicode.com/me.getValue();
System.out.println(key+":"+value);
}
}
public static void method_values(Map<Integer,String> map){
map.put(8, "wangcai");
map.put(2, "zhangsan");
map.put(7, "zhaoliu");
map.put(6, "yaoming");
Collection<String> values=map.values();
Iterator<String> it=values.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
Map常用的子类:
HashTable:内部结构是哈希表,是同步的。不支持null作为键和null作为值。
properties:HashTable的一个子类对象,用来存储键值类型的配置文件的信息,可以和IO技术相结合,所以相当牛逼。
HashMap:内部结构是哈希表,不是同步的。支持null作为键和null作为值。
TreeMap:内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。
HashMapDemo演示:
package day18;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import Class.Student;
public class HashMapDemo {
/**
* 将对象和学生的归属地通过键与值存储到map集合中
*/
public static void main(String[] args) {
HashMap<Student,String> hm=new HashMap<Student,String>();
hm.put(new Student("lisi",18),"北京");
hm.put(new Student("zhangsan",19),"西安");
hm.put(new Student("wangwu",28),"深圳");
hm.put(new Student("xiaoqiang",24),"铁岭");
hm.put(new Student("xiaoqiang",24),"上海");//注意这里要重写HashCode和equals,
//要不然这个对象和上面对象的键相同,上海就会被铁岭覆盖。
Set<Student> KeySet=hm.keySet();
Iterator<Student> it=KeySet.iterator();
//其实上面这两句等于这一句:Iterator<Student> it=hm.keySet().iterator;
while(it.hasNext()){
Student key=it.next();
String value=http://www.mamicode.com/hm.get(key);
System.out.println(key.getName()+":"+key.getAge()+"---"+value);
}
}
}
输出结果为:
wangwu:28---深圳
lisi:18---北京
zhangsan:19---西安
xiaoqiang:24---上海
xiaoqiang:24---铁岭
TreeMapDemo演示:
package day18;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import Class.Student;
import Comparator.ComparatorByName;
public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Student,String> tm=new TreeMap<Student,String>(new ComparatorByName());
tm.put(new Student("lisi",18),"北京");
tm.put(new Student("zhangsan",19),"西安");
tm.put(new Student("wangwu",28),"深圳");
tm.put(new Student("xiaoqiang",24),"铁岭");
tm.put(new Student("xiaoqiang",24),"上海");//注意这里要重写HashCode和equals,
//要不然这个对象和上面对象的键相同,上海就会被铁岭覆盖。
Iterator<Map.Entry<Student, String>> it=tm.entrySet().iterator();
while(it.hasNext()){
Map.Entry<Student, String> me=it.next();
Student key=me.getKey();
String value=http://www.mamicode.com/me.getValue();
System.out.println(key.getName()+":"+key.getAge()+"---"+value);
}
}
}
输出结果为:(TreeMap不能重复)
lisi:18---北京
wangwu:28---深圳
xiaoqiang:24---上海
zhangsan:19---西安
泛型(generic):jdk1.5出现的安全机制。
好处:
1.将运行时起的问题ClassCastException转到了编译时期。
2.避免了强制转换的麻烦。
什么时候用<>?
当操作的引用数据类型不确定时就使用<>,将要操作的引用数据类型传入即可。
其实<>就是一个用于接收具体引用数据类型的参数范围。
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型。
泛型技术是给编译器使用的技术,用于编译时期,确保了类型的安全。
运行时,会将泛型去掉,生成的class文件中是不带泛型的,这称为泛型的擦除。
为什么要擦除呢?这是为了兼容运行的类加载器。
泛型的补偿:在运行时,通过获取元素的类型进行转换动作,不用使用者再强制转换了。
在jdk1.5后,使用泛型类来接收类中要操作的引用数据类型。
这就是泛型类。什么时候用?当类中操作的引用数据类型不确定时,就要用泛型表示。
静态方法不能访问类上定义的泛型,如果静态方法只用到了泛型,只能定义在方法上
泛型接口:将泛型定义在接口上。
LinkedHashMap:和HashMap一个用法,只不过这是有序的,这里的有序是指咋存进去,咋取出来。
Map集合在有映射关系时,可以优先考虑。在查表法中的应用较为多见。
package day18;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class MapTest {
/**
* 练习:"fdg avcb+sac/*dfSs"获取该字符串中,每一个字母出现的字数。
* 要求打印结果是a(2)b(0)....
*
* 思路:
* 对于结果的分析发现,字母和次数之间存在着映射关系,而且很多。
* 这就需要存储了,能存储映射关系的容器有数组和map集合。
* 关系的一方是有序编号吗?没有,所以就要用map集合了。
* 又发现可以保证唯一性的一方具备着顺序如a b c... 所以就用TreeMap集合了。
*
* 这个集合中最终应该存储的是字母和次数的对应关系。
* 1.因为操作的是字符串中的字母,所以先将字符串变成字符数组。
* 2.遍历字符数组,用每一个字母作为键值,去查map集合这个表。
* 如果该字母不存在,就将该字母作为键存储到map集合中。
* 如果该字母存在,就将该字母键对应值取出并+1,再将该字母键和+1后的值存储到map集合中。
* 键相同值会覆盖,这样就记录住了该子母出现的次数。
* 3.遍历结束,map集合记录了所有字母以及出现的次数。
*/
public static void main(String[] args) {
String str="fdgavcbsacdfss";
String s=getCharCount(str);
System.out.println(s);
}
public static String getCharCount(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;
//将数组中的字母作为键去查map表。这里用ContainsKey比较麻烦,直接用get,为空就说明没有这个字母
int count=1;
Integer value=http://www.mamicode.com/map.get(chs[i]);
/*这几句比较符合逻辑,容易理解,但通常不这么写。
if(value=http://www.mamicode.com/=null)
map.put(chs[i], 1);
else
map.put(chs[i], value+1);
*/
if(value!=null){
count=value+1;
}
map.put(chs[i], count);
}
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=http://www.mamicode.com/map.get(key);
sb.append(key+"("+value+")");
}
return sb.toString();
}
}
Utilities(工具)
Collections:(注意不带S的是接口,带S的是工具类)
集合框架的工具类,里面的方法都是静态的。
Arrays:集合框架的工具类,方法也都是静态的。
Collections演示:
package day18;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;
import Comparator.ComparatorByLength;
//Collections是集合框架的工具类,里面的方法都是静态的。
public class ToolCollectionsDemo {
public static void main(String[] args) {
demo_1();
demo_2();
demo_3();
demo_4();
demo_5();
}
public static void demo_1(){
List<String> list=new ArrayList<String>();
list.add("kk");
list.add("abcde");
list.add("cba");
list.add("zzz");
list.add("cba");
list.add("nbaa");
System.out.println(list);
//对list集合进行指定顺序的排序。
Collections.sort(list); //直接调用工具类的Sort方法
System.out.println(list);
mySort(list); //自己写的一个排序方法,可以看出最终结果和Sort一样。
Collections.sort(list,new ComparatorByLength());
System.out.println(list);
}
public static <T extends Comparable<? super T>> void mySort(List<T> list){ //加了泛型,而且T必须具备可比较性,提高了程序拓展性
//public static void mySort(List<String> list){ //写这句拓展性不高,只能给String排序
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);
}
}
}
System.out.println(list);
}
public static void demo_2(){ //颠倒顺序的方法
TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));
ts.add("abc");
ts.add("hahaha");
ts.add("a");
ts.add("nba");
ts.add("mlgb");
System.out.println(ts);
}
public static void demo_3(){
List<String> list=new ArrayList<String>();
list.add("kk");
list.add("abcde");
list.add("cba");
list.add("zzz");
list.add("cba");
list.add("nbaa");
System.out.println(list);
Collections.replaceAll(list,"cba", "nba"); //替换的方法,把cba改成nba 原理就是用indexOf方法加set方法
System.out.println(list);
}
public static void demo_4(){
List<String> list=new ArrayList<String>();
list.add("kk");
list.add("ab");
list.add("cba");
System.out.println(list);
Collections.fill(list, "cc"); //将集合中的所有值全部替换。
System.out.println(list);
}
public static void demo_5(){
List<String> list=new ArrayList<String>();
list.add("xiaoqiang");
list.add("wangcai");
list.add("zhaoliu");
System.out.println(list);
Collections.shuffle(list); //随机重新排列集合元素的顺序。
System.out.println(list);
}
}
List asList(数组)将数组转成集合。
* 好处:可以使用集合的方法操作数组中 的元素
*
* 注意:数组长度固定,所以不能使用增和删方法,否则异常
* 如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
* 如果数组中的原始是基本类型数值, 那么会将该数组作为集合中的元素进行存储。
集合转数组:
* 使用的就是Collection接口中的toArray方法
* 好处:可以对集合中的元素操作的方法进行限定,不允许对其增删
* toArray方法需要传入一个指定类型的数组。
* 如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。
* 如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为null。
* 所以建议最好长度指定为集合的size。
foreach语句:
格式:for(类型 变量:Collection集合或数组){
}
例子:List<String> list=new ArrayList<String>
list.add("abc1");
list.add("abc2");
list.add("abc3");
/*原来这么写:、
iterator<String> it=list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}*/
for(String s:list){
System.out.println(it.next());
} //这个就是用来简化书写的,可以遍历集合,也可以遍历数组
传统for和增强for的区别?
传统for可以完成对语句执行很多次,因为可以控制循环的增量和条件
增强for是一种简化形式,必须有遍历的目标,要么是集合,要么是数组。
对数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。
如果要对数组的角标进行操作,建议使用传统for。
高级for只能遍历单列集合,所以不能直接遍历map,要将map转成set才能用。
函数的可变参数
其实就是一个数组,但是接受的是数组的元素,自动将这些元素封装成数组,简化了书写。
注意:可变参数类型,必须定义在参数列表的结尾处。
public class newAddDemo {
/**
* @param args
*/
public static void main(String[] args) {
int sum=newAdd(1,2,3);
System.out.println(sum);
int sum1=newAdd(1,2,3,4,5);
System.out.println(sum1);
}
//函数的可变参数int ...
//注意可变参数类型必须定义在参数列表的结尾,比如newAdd(int x,int... arr)
public static int newAdd(int... arr) {
int sum=0;
for (int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
return sum;
}
}
本文出自 “12946849” 博客,请务必保留此出处http://12956849.blog.51cto.com/12946849/1932020
java(八)集合