------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
1.Map集合:
(1)Map集合的特点:
1、接口Map<k,v>:必须存2个元素,而且两个元素之间有映射关系。
2、该集合存储键值对,一对一对的往里存,需要保证键的唯一性。
3、是一个双列集合,Collection是单列集合。
(2)Map集合的常用方法:
void putAll(Map<? extends K,? extends V> m);
Put方法的特点:如果要添加的键在集合中已经存在了,那么会
覆盖以前的键,并且会将以前的值返回。
2、删除: void clear();
V remove(Object key);
3、判断:boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
boolean equals(Object o);
4、获取:V get(Object key);
int hasCode();
int size();
Collection<V> values();
Set<Map.Entry<K,V>> entrySet();
Set<k> keySet();
(3)Map集合的子类:
1、HashMap:
底层是哈希表数据结构,允许使用null键和null值,该集合
是不同步的,效率高。
2、TreeMap:
底层是二叉树数据结构,线程不同步,可以给Map集合中的
键进行排序。
3、Hashtable:
底层是哈希表数据结构,线程同步,不可以存入null键和
null值,该集合是线程同步的。为了成功的在哈希表中存储和获取对象,
用做键的对象 必须实现hashCode和equals方法。
(4)Map集合的取出方式一:
keySet();方法:
代码例子:
import java.util.*;
class MapDemo1
{
public static void main(String[] args)
{
Map<String,String> map =new HashMap<String,String>();
map.put("02","zhangsan");
map.put("05","lisi");
map.put("06","wangwu");
map.put("01","zhaoliu");
//获取Map集合所有键的Set集合。
Set<String> keySet =map.keySet();
//获取到Set集合就可以用迭代器迭代了。
Iterator<String> it = keySet.iterator();
while(it.hasNext())
{
//Set集合中取出的是所有的键。
String key =it.next();
//获取到键以后就可以用Map集合的get方法获取其对应的值。
String value =map.get(key);
System.out.println(key+".."+value);
}
}
}
(5)Map集合的取出方式二:
entrySet();
代码例子:
import java.util.*;
class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map =new HashMap<String,String>();
map.put("02","zhangsan");
map.put("05","lisi");
map.put("06","wangwu");
map.put("01","zhaoliu");
//将Map集合中的映射关系取出存入Set集合。
Set<Map.Entry<String,String>> entrySet =map.entrySet();
//用迭代器进行迭代。
Iterator<Map.Entry<String,String>> it = entrySet.iterator();
while(it.hasNext())
{
//取出的是Map集合中的映射关系。
Map.Entry<String,String> kv =it.next();
//获取键,通过Map.Entry中的getKey()方法。
String key = kv.getKey();
//获取值,通过Map.Entry中的getValue()方法。
String value =kv.getValue();
System.out.println(key+".."+value);
}
}
}
注意:Map.Entry也是一个接口,它是Map集合中的一个内部接口。
代码例子:
interface Map
{
//是Map的内部接口,并且是静态的,对外公开,也能够产生class文件。
public static interface Entry
{
public abstract void getKey();
public abstract void getValue();
}
}
class HashMap implements Map
{
//内部类实现了Entry。
class Hash implements Map.Entry
{
//复写了接口接口中的抽象方法。
public void getKey(){}
public void getValue(){}
}
}
(6)练习一
需求:实现自定一个学生对象和地址,使用HashMap。
学生:Student 地址:String
学生属性:姓名,年龄
注意:同姓名同年龄为同一个人
需要保证学生的唯一性
代码例子:
import java.util.*;
class Student implements Comparable<Student>
{
private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public void setName(String name)
{
this.name=name;
}
public void setAge(int age)
{
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
//复写equals方法。
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s =(Student)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
//复写hashCode方法。
public int hashCode()
{
return name.hashCode()+age*34;
}
/*复写compareTo方法,让元素具备自然顺序,因为有可能存到 TreeMap集合中。*/
public int compareTo(Student s)
{
int num =new Integer(this.age).compareTo(new Integer(s.age));
if(num==0)
return this.name.compareTo(s.name);
return num;
}
}
class MapTest1
{
public static void main(String[] args)
{
Map<Student,String> map =new HashMap<Student,String>();
map.put(new Student("lisi1",21),"beijing");
map.put(new Student("lisi2",22),"shanghai");
map.put(new Student("lisi3",23),"guangdong");
map.put(new Student("lisi4",24),"wuhan");
//获取Map集合所有键的Set集合。
Set<Student> keySet= map.keySet();
Iterator<Student> it =keySet.iterator();
while(it.hasNext())
{
//取出的是学生对象。
Student stu=it.next();
//根据取出的学生对象键,获取到地址。
String addr=map.get(stu);
System.out.println(stu.getName()+".."+stu.getAge()+".."+addr);
}
}
}
打印结果:
lsi4..24..wuhan
lisi2..22..shanghai
lisi1..21..beijing
lisi3..23..guangdong
(7)练习二
需求:对(6)中学生对象的年龄进行升序排序。
使用TreeMap集合。
代码例子:将(6)中的集合改成TreeMap。
class MapTest2
{
public static void main(String[] args)
{
Map<Student,String> map =new TreeMap<Student,String>();
map.put(new Student("lisi1",21),"beijing");
map.put(new Student("lisi2",22),"shanghai");
map.put(new Student("lisi3",23),"guangdong");
map.put(new Student("lisi4",24),"wuhan");
//获取Map集合所有键的Set集合。
Set<Student> keySet= map.keySet();
Iterator<Student> it =keySet.iterator();
while(it.hasNext())
{
//取出的是学生对象。
Student stu=it.next();
//根据取出的学生对象键,获取到地址。
String addr=map.get(stu);
System.out.println(stu.getName()+".."+stu.getAge()+".."+addr);
}
}
}
打印结果为:
lisi1..21..beijing
lisi2..22..shanghai
lisi3..23..guangdong
lisi4..24..wuhan
(8)练习三
需求:获取字符串中的字母出现的次数。
希望打印结果为:a(1) b(2)......
发现每一个字母都有对应的次数,说明字母与数字之间有映射关系,
所以可以使用Map集合。
步骤:
1、将字符串转换成字符数组,因为要对每一个字母进行操作。
2、定义一个Map集合,使用TreeMap因为打印结果有顺序。
3、将每一个字母作为键去查Map集合,如果返回的是null,
就将该字母和1存入到Map集合中,如果返回的不是null,
说明字母已经在集合中存在了并且对应了次数,那么就获取
该次数进行自增,然后将自增后的字母和次数存入到集合中。
4、将Map集合中的数据按照指定的字符串返回。
代码例子:
import java.util.*;
class MapTest3
{
public static void main(String[] args)
{
String s =charCount("abchacbdf");
System.out.println(s);
}
public static String charCount(String str)
{
char[] chs = str.toCharArray();
TreeMap<Character,Integer> tm= new TreeMap<Character,Integer>();
for(int x=0; x<chs.length; x++)
{
if(!(chs[x]>='a'&&chs[x]<='z'||chs[x]>='A'&&chs[x]<='Z'))
continue;
Integer value =tm.get(chs[x]);
if(value==null)
{
//count = value;
tm.put(chs[x],1);
}
else
{
value = value+1;
tm.put(chs[x],value);
}
}
StringBuilder sb =new StringBuilder();
Set<Map.Entry<Character,Integer>> entryKey=tm.entrySet();
Iterator<Map.Entry<Character,Integer>> it=entryKey.iterator();
while(it.hasNext())
{
Map.Entry<Character,Integer> me=it.next();
Character ch =me.getKey();
Integer value = me.getValue();
sb.append(ch+"("+value+")");
}
return sb.toString();
}
}
2.Map集合扩展知识:
需求:集合嵌套集合,
有一个学校,学校有两个班,每个班有二个学生,有学号和姓名。
取出这学校所以班的所有学生。
代码例子:
import java.util.*;
class Student //定义一个学生类。
{
private String name;
private String id;
Student(String name,String id)
{
this.name=name;
this.id=id;
}
public void setName(String name)
{
this.name=name;
}
public void setId(String id)
{
this.id=id;
}
public String getId()
{
return id;
}
public String getName()
{
return name;
}
}
class MapTest4
{
public static void main(String[] args)
{
//班级与学生产生映射关系,所以用Map集合定义学校。
HashMap<String,List<Student>> xuexiao =
new HashMap<String,List<Student>>();
//用List集合定义班级来存储学生对象。
List<Student> yiban =new ArrayList<Student>();
//一班有两个学生。
yiban.add(new Student("01","zhangsan"));
yiban.add(new Student("02","lisi"));
List<Student> erban =new ArrayList<Student>();
//二班有两个学生。
erban.add(new Student("01","wangwu"));
erban.add(new Student("02","zhaoliu"));
//将这个两个班级添加进Map集合,也就是学校。
xuexiao.put("yiban",yiban);
xuexiao.put("erban",erban);
//遍历Map集合,将键取出,也就是将学校取出。
Iterator<String> it= xuexiao.keySet().iterator();
while(it.hasNext())
{
String roomname =it.next();
//根据键获取值,也就是获取学生对象。
List<Student> room = xuexiao.get(roomname);
System.out.println(roomname);
getInfos(room);
}
}
public static void getInfos(List<Student> list)
{
//遍历List集合,取出学生的学号和姓名。
Iterator<Student> it1 =list.iterator();
while(it1.hasNext())
{
Student s =it1.next();
System.out.println(s.getId()+".."+s.getName());
}
}
}
打印结果为:
yiban
01..zhangsan
02..lisi
erban
01..wangwu
02..zhaoliu
3.Collections 集合工具类:
(1)Collection与Collections的集合的区别:
Collection是一个接口,里面是包含了各种集合容器。
Collections是一个工具类,里面包含了各种用来操作Collection实例类的
的方法,里面的方法都是静态的,泛型要定义在方法上,可以对List集合
进行排序。
(2)Collections里面有那些常用的方法:
1、sort()
2、max(Collection<? extends T> coll) 根据元素的自然顺序,返回给定
collection 的最大元素。
max(Collection<? extends T> coll, Comparator<? super T> comp)
根据比较器产生的顺序,返回给定 collection 的最大元素。
3、binarySearch(List<? extends Comparable<? super T>> list,T key)
接收的是自然顺序比较。
binarySearch(List<? extends T> list, T key,Comparator<? super T> c)
接收的是比较器。
4、fill(List<? super T> list, T obj) 使用指定元素替换指定列表中的所有元素。
5、replaceAll(List<T> list, T oldVal, T newVal) 使用另一个值替换列表中出现
的所有某一指定值。
6、reverseOrder()返回一个比较器,它强行逆转实现了Comparable 接口的
对象 collection 的自然顺序。
注意:使用二分搜索法搜索指定列表,以获得指定对象。必须是List集合,因为涉及到角标,而且集合必须是有序的
才能使用这个方法。
(3)sort方法的应用:
是给List集合排序用的,比如我们在List集合里面存了一个学生对象,那我们要用Collections里面的sort方法对List集合
进行排序,但是学生对象不具备比较性,那么就绪要泛型限定:
代码例子:
public static<T extends Comparable<? super T >> void sort(List<T> list){}
T必须是Comparable的子类,也就是必须实现Comparable,Comparable里面还可以传T或者T的父类。在比较的时候调用了Comparable内部的compareTo方法。
代码例子:
1、自然排序:
import java.util.*;
class CollectionsDemo
{
public static void main(String[] args)
{
sortDemo();
}
public static void sortDemo()
{
List<String> al=new ArrayList<String>();
al.add("abcd");
al.add("aaa");
al.add("z");
al.add("kkkk");
al.add("qq");
Collections.sort(al);
Iterator<String> it=al.iterator();
while(it.hasNext())
{
String s =it.next();
System.out.println(s);
}
}
}
打印结果为:
aaa
abcd
Kkkk
z
2、如果按照长度排序,需要定义一个比较器,实现Comparator接口。
代码例子:
import java.util.*;
class CollectionsDemo1
{
public static void main(String[] args)
{
sortDemo();
}
public static void sortDemo()
{
List<String> al=new ArrayList<String>();
al.add("abcd");
al.add("aaa");
al.add("bbb");
al.add("z");
al.add("kkkk");
al.add("qq");
//往sort集合中传一个比较器对象。
Collections.sort(al,new CollectionsDemo2());
Iterator<String> it=al.iterator();
while(it.hasNext())
{
String s =it.next();
System.out.println(s);
}
}
}
//实现Comparator接口。
class CollectionsDemo2 implements Comparator<String>
{
//覆盖compare方法。
public int compare(String s1,String s2)
{
int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
}
}
打印结果:
z
aaa
bbb
abcd
kkkk
(4)Max方法的应用:
import java.util.*;
class CollectionsDemo1
{
public static void main(String[] args)
{
maxDemo();
}
public static void maxDemo()
{
List<String> al=new ArrayList<String>();
al.add("abcd");
al.add("aaa");
al.add("bbb");
al.add("z");
al.add("kkkk");
al.add("qq");
String max =Collections.max(al);
System.out.println(max);
}
打印结果是:z
如果加上比较器:
代码改成:
String max =Collections.max(al,new CollectionsDemo2());
class CollectionsDemo2 implements Comparator<String>
{
public int compare(String s1,String s2)
{
int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
}
}
打印的结果是 kkkk
也就是打印的长度最大的元素。
(5)binarySearch方法的应用:
1、代码例子:
import java.util.*;
class CollectionsDemo3
{
public static void main(String[] args)
{
indexDemo();
}
public static void indexDemo()
{
List<String> al=new ArrayList<String>();
al.add("aaa");
al.add("abcd");
al.add("bbb");
al.add("kkkk");
al.add("qq");
al.add("z");
//调用binarySearch查找”z”。
int index =Collections.binarySearch(al,"z");
//打印结果为5。
System.out.println(index);
}
}
注意:如果查找的是”zz”,那么打印结果就是-7,当要查找的元素不存在时,就返回负数,这个负数就是插入点前面价格负数再减一,插入点就是指如果这个元素存在于集合中,那么它应该存在于什么位置,这个位置就是插入点。
如果List集合中的元素不具备比较性,也就是没有实现Comparable接口,那么就用binarySearch方法的第二种形式,里面接收的是一个比较器。
2、那么代码改成:
import java.util.*;
class CollectionsDemo3
{
public static void main(String[] args)
{
indexDemo();
}
public static void indexDemo()
{
List<String> al=new ArrayList<String>();
al.add("aaa");
al.add("abcd");
al.add("bbb");
al.add("kkkk");
al.add("qq");
al.add("z");
//调用binarySearch形式2查找”z”。
int index =Collections.binarySearch(al,"z",new CollectionsDemo4());
//打印结果为5。
System.out.println(index);
}
}
class CollectionsDemo4 implements Comparator<String>
{
public int compare(String s1,String s2)
{
int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
}
}
(6)fill方法的应用:
代码例子:
import java.util.*;
class CollectionsDemo5
{
public static void main(String[] args)
{
//sortDemo();
fillDemo();
}
public static void fillDemo()
{
List<String> al=new ArrayList<String>();
al.add("aaa");
al.add("abcd");
al.add("bbb");
//调用Collections中的fill方法将List集合中的全部元素都替换成”pp”。
Collections.fill(al,"pp");
Iterator<String> it = al.iterator();
while(it.hasNext())
{
String s=it.next();
System.out.println(s);
}
}
}
打印的结果是:
pp
pp
pp
如果想替换部分元素,那么就分别设置就行,al.set(0,”pp”);
(7)replaceAll方法的应用:
代码例子:
import java.util.*;
class CollectionsDemo6
{
public static void main(String[] args)
{
//sortDemo();
int start=0;
int end =3;
replaceAllDemo();
}
public static void replaceAllDemo()
{
List<String> al=new ArrayList<String>();
al.add("aaa");
al.add("abcd");
al.add("bbb");
//调用Collections中的replaceAll方法将集合中的元素”bbb”替换成”www”。
Collections.replaceAll(al,"bbb","www");
Iterator<String> it = al.iterator();
while(it.hasNext())
{
String s=it.next();
System.out.println(s);
}
}
}
打印结果为:
aaa
abcd
www
(8)reverseOrder方法的应用:
代码例子:
import java.util.*;
class CollectionsDemo7
{
public static void main(String[] args)
{
reverseOrderDemo();
}
public static void reverseOrderDemo()
{
/*在TreeSet的构造函数中接收一个Collections的reverseOrder方法返回
一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的
自然顺序。*/
TreeSet<String> ts=new TreeSet<String>(Collections.reverseOrder());
ts.add("aaa");
ts.add("abcd");
ts.add("bbb");
Iterator<String> it = ts.iterator();
while(it.hasNext())
{
String s=it.next();
System.out.println(s);
}
}
}
打印结果为:
bbb
abcd
aaa
4.Arrays工具类:
Arrays工具类的作用:用于操作数组的工具类,里面都是静态方法。
(1)将数组变成List集合:
用到了Arrays中的asList方法。
将数组变成List集合的好处:
1、可以使用集合的思想和方法操作数组中的元素。
2、数组是一个对象,功能比较少,List是一个集合功能比较多。
注意:将数组变成List集合,不可以使用集合的增删方法,因为数组的的长度
是固定的。
代码例子:
import java.util.*;
class ArraysDemo
{
public static void main(String[] args)
{
//定义一个字符串数组。
String[] arr={"abc","cc","kkkk"};
//调用Arrays中的asList方法,将数组变成List集合。
List<String> list =Arrays.asList(arr);
System.out.println(list);
}
}
打印结果为:[abc,cc,kkkk]
如果定义一个int型的数组呢?
代码例子:
import java.util.*;
class ArraysDemo
{
public static void main(String[] args)
{
int[] num={1,2,3,4};
List<int[]> list =Arrays.asList(num);
System.out.println(list);
}
}
打印结果为:哈希值。
那么为什么呢?
因为如果数组中的元素都是对象的话,那么就可以直接转成集合中的元素,就如同String数组,如果数组里面的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
如果写成是Integer数组的话,就可以了,因为Integer有自动装箱和拆箱的功能。
代码例子:
import java.util.*;
class ArraysDemo
{
public static void main(String[] args)
{
Integer[] num={1,2,3,4};
List<Integer> list =Arrays.asList(num);
System.out.println(list);
}
}
//打印结果为:[1,2,3,4]
(2)集合转成数组。
用的是Collection接口中的toArrayT[] a方法,
代码例子:
import java.util.*;
class CollectionToArray
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>();
al.add("abc1");
al.add("abc2");
al.add("abc3");
/*将集合变成数组,指定一个集合中元素的个数,
也就是指定数组的长度。*/
String[] arr = al.toArray(new String[al.size()]);
//以字符串的形式打印出来。
System.out.println(Arrays.toString(arr));
}
}
//打印结果为:[abc1,abc2,abc3]
那么指定类型的数组长度到底定义多长呢?
1、当指定的长度小于集合的长度,该方法内部会自动创建一个该类型的新数
组长度和集合长度一致 。用于存储集合中的元素。
2、如果指定的数组长度大于集合的长度,那么该方法就不会创建新数组。而
是使用传递进来的数组,存储完集合的元素后,其他的未存储的位置为null。
3、所以在定义数组是,最好定义长度和集合长度相同的数组,这样就不用创建新数组了,而且也不会出现空位为
null 。
那么为什么要将集合变成数组?
是为了限定对元素的操作,变成数组以后就不能进行增删操作了。
------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------