------- android培训、java培训、期待与您交流! ----------
集合(下)
Map接口的实现类
Map皆空常用的实现类有Hashtable,HashMap和TreeMap,通常建议使用HashMap结合实现Map集合,因为HashMap类实现Map集合对于天价和删除
映射关系效率更高.HashMap是给予哈希表的Map接口的实现,HashMap通过哈希吗对其内部的映射关系进行快速查找;由HshMap类实现Map集合对于天价或者删除
映射关系效率高;而TreeMap中的映射关系存在一定的顺序,如果希望Map集合中的对象存在一定的顺序,应该使用TreeMap类实现Map集合.Map和Set很像。
Set底层就是使用了Map集合。
Map与Collection:
Map与Collection在集合框架中属并列存在
Map存储的是键值对
Map存储元素使用put方法,Collection使用add方法
Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素
Map集合中键要保证唯一性
Map集合特点:
该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
//-----------------------------华丽的分割线------------------------------------
Map集合的共性方法:
1,添加。
put(K key, V value)
putAll(Map<? extends K,? extends V> m)
2,删除。
clear()
remove(Object key)
3,判断。
containsValue(Object value)
containsKey(Object key)
isEmpty()
4,获取。
get(Object key)
size()
values()
entrySet()
keySet()
//-----------------------------华丽的分割线------------------------------------
import java.util.*;
class MapDemo
{
public static void main(String[] args)
{
//建立Map集合
Map<String,String> map=new HashMap<String,String>();
////添加元素,添加元素,如果出现添加时,相同的键。那么后添加的值会覆盖原有键对应值。
map.put("01","zhangsan1");
map.put("02","zhangsan2");
map.put("03","zhangsan3");
map.put("04","zhangsan4");
sop(map.containsKey("02"));//判断键是否存在
sop(map.get("01"));//可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。
sop(map);
Collection<String> coll=map.values();//用values获取map集合中所有的值.
sop(coll);
}
public static void sop(Object obj)//为了打印方便建立一个函数
{
System.out.println(obj);
}
}
//-----------------------------华丽的分割线------------------------------------
map集合的两种取出方式:
1,Set<k> keySet:
将map中所有的键存入到Set集合。因为set具备迭代器。
所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
Map集合的取出原理:
将map集合转成set集合。在通过迭代器取出。
示例:
import java.util.*;
class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map=new HashMap<String,String>();
map.put("01","zhansan01");
map.put("02","zhansan02");
map.put("03","zhansan03");
map.put("04","zhansan04");
Set<String> s=map.keySet();//先获取map集合的所有键的Set集合,keySet();
System.out.println(map);//有了Set集合。就可以获取其迭代器。
for(Iterator<String> it=s.iterator(); it.hasNext();)
{
String key=it.next();
//有了键可以通过map集合的get方法获取其对应的值。
String value=map.get(key);
System.out.println(key+"..."+value);
}
}
}
2,Set<Map.Entry<k,v>> entrySet:
将map集合中的映射关系存入到了set集合中,
而这个关系的数据类型就是:Map.Entry
Entry其实就是Map中的一个static内部接口。
为什么要定义在内部呢?
因为只有有了Map集合,有了键值对,才会有键值的映射关系。
关系属于Map集合中的一个内部事物。
而且该事物在直接访问Map集合中的元素。
示例:
import java.util.*;
class MapDemo3
{
public static void main(String[] args)
{
Map<Integer,String> map=new HashMap<Integer,String>();
map.put(01,"java01");
map.put(02,"java02");
map.put(03,"java03");
map.put(04,"java04");
//将Map集合中的映射关系取出。存入到Set集合中。
Set<Map.Entry<Integer,String>> entrySet=map.entrySet();
for(Iterator<Map.Entry<Integer,String>> it=entrySet.iterator();it.hasNext();)
{
Map.Entry<Integer,String> me=it.next();
Integer key=me.getKey();
String value=me.getValue();
System.out.println(key+"...."+value);
}
}
}
//-----------------------------华丽的分割线------------------------------------
HashSet示例:
/*
1.描述学生.
2.定义map容器.将学生作为键.住址作为值,存入.
3.获取map集合中的元素
*/
import java.util.*;
class Student implements Comparable<Student>//为了以后方便可能存进去TreeSet集合中去实现Comparable.将学生具备比较性
{
private String name;
private int age;
Student(String name,int age)//将学生name和age初始化
{
this.name=name;
this.age=age;
}
public int compareTo(Student s)//覆盖Comparable中的compareTo方法.来比较,先比较age在比较name.
{
int num=new Integer(this.age).compareTo(new Integer(s.age));//Integer是因为age是基本数据类型不具备比较.要转成Integer来实现compareTo方法
if(num==0)
return this.name.compareTo(s.name);//name是字符串本身就比较比较性.直接使用compareTo方法就哦了
return num;
}
public int hashCode()//复写hashCode.来让存进去的学生保证唯一.为什么要覆盖因为默认比较是比较hash值.和内容是否一样.因为存的是hash值所以每次建立对象的时候都不一样
//所以要复写hashCode,来比较年龄和姓名是否是相同.这样就能保证学生的唯一性了.
{
return name.hashCode()+age*34;
}
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;
}
public String getName()
{
return name;
}
public int getInt()
{
return age;
}
public String toString()
{
return name+".."+age;
}
}
class MapTest
{
public static void main(String[] args)
{
HashMap<Student,String> hm=new HashMap<Student,String>();//穿件Map集合中的 HashMap集合
hm.put(new Student("zhangsan01",21),"beijing");//往里面添加键值对.将学生作为键.住址作为值
hm.put(new Student("zhangsan02",22),"tianjing");
hm.put(new Student("zhangsan03",23),"sahgnhan");
hm.put(new Student("zhangsan01",23),"sahgnhan");
//第一种去取出方式
Set<Student> s=hm.keySet();
for(Iterator<Student> it=s.iterator();it.hasNext();)
{
Student key=it.next();
String value=hm.get(key);
System.out.println(key+"...."+value);
}
//第二种取出方式
System.out.println("-----------------------------------------------------");
Set<Map.Entry<Student,String>> entrySet=hm.entrySet();
for(Iterator<Map.Entry<Student,String>> it=entrySet.iterator();it.hasNext();)
{
Map.Entry<Student,String> me=it.next();
Student key1=me.getKey();
String value1=me.getValue();
System.out.println(key1+"..."+value1);
}
}
}
//-----------------------------华丽的分割线------------------------------------
集合方法方法类
Collections类:集合框架的工具类。
Collections:集合框架的工具类。里面定义的都是静态方法。
Collections.方法( );
Collections和Collection有什么区别?
Collection
是集合框架中的一个顶层接口,
它里面定义了单列集合的共性方法。它有两个常用的子接口,List:对元素都有定义索引。有序的。
可以重复元素。Set:不可以重复元素。无序。
Collections
是集合框架中的一个工具类。该类中的方法都是静态的
1提供的方法中有可以对list集合进行排序,二分查找等方法。
2通常常用的集合都是线程不安全的。因为要提高效率。
3如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
Collections的常用方法:
sort:对List集合排序
public static <T extends Comparable<? super T>> void sort(List<T> list)
根据元素的自然顺序 对指定列表按升序进行排序。列表中的所有元素都必须实现 Comparable 接口
Collections.sort(list);
不可以给Set排序因为Set里面有TreeSet.用它也没什么用
如果出现了重复元素也可以排序,因为是数组结构有索引.
Collections.sort(list,new 比较器Comparator);
如果不喜欢默认的排序可以自定义比较器(比如最大长度
max:获取最大值
public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp)
根据指定比较器产生的顺序,返回给定 collection 的最大元素。collection 中的所有元素都必须可通过指定比较器相互比较
(也就是说,对于 collection 中的任意 e1 和 e2 元素,comp.compare(e1, e2) 不得抛出 ClassCastException)。
String max=Collection.max(list);
String max=Collection.max(list,new 比较器Comparator);
也可以放比较器.最大程度等
binarySearch:对list集合二分查找(必须是有序的)
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序
对列表进行升序排序(通过 sort(List) 方法)。如果没有对列表进行排序,则结果是不确定的。如果列
表包含多个等于指定对象的元素,则无法保证找到的是哪一个。
返回:
如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。
插入点 被定义为将键插入列表的那一点:即第一个大于此键的元素索引;如果列表中的所有元素都
小于指定的键,则为 list.size()。注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。
Collection.sort(list);//对list集合进行排序
int index =Collection.binarySearch(list,"aaa");//查找"aaa"所在位置.返回插入点-1
System.out.println("index"+index);
(也可以加入比较器.比如长度排序,传比较器)
Collection.sort(list,new 比较器Comparator);//对list集合进行长度排序
int index =Collection.binarySearch(list,"aaa"new 比较器Comparator);//查找"aaa"所在位置.(按长度来了)返回插入点-1
System.out.println("index"+index);
fill:将集合中的部分元素替换成指定元素
public static <T> void fill(List<? super T> list,T obj)使用指定元素替换指定列表中的所有元素。
Collection.fill(list,"pp");
replaceAll:替换
public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal)
使用另一个值替换列表中出现的所有某一指定值。更确切地讲,使用 newVal 替换 list 中
满足 (oldVal==null ? e==null : oldVal.equals(e)) 的每个 e 元素。(此方法对列表的大小
没有任何影响。)
Collection.replaceAll(list,"aaa","PP");//将"aaa"替换成"pp"
reverse:反转.
Collection.reverse(list);//将list反转
reverseOrder:逆转排序
返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。
TreeSet<String> ts=new TreeSet<String>(Collection.reverseOrder(new 比较器());
synchronizedList:给不同步.返回同步的
public static <T> List<T> synchronizedList(List<T> list)
返回指定列表支持的同步(线程安全的)列表。为了保证按顺序访问,必须通过返回的列表完成所有对底层实现列表的访问。
在返回的列表上进行迭代时,用户必须手工在返回的列表上进行同步:
synchronizedMap
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
synchronizedSet
public static <T> Set<T> synchronizedSet(Set<T> s)
swap:在指定列表的指定位置处交换元素。
public static void swap(List<?> list,int i,int j)
在指定列表的指定位置处交换元素。(如果指定位置相同,则调用此方法不会更改列表。)
Collection.swap(list,1,2);//将list集合的角标1和角标2互换
shuffle:把集合中的元素随机的排放
public static void shuffle(List<?> list)
使用默认随机源对指定列表进行置换。所有置换发生的可能性都是大致相等的。
Collection.shuffle(list);//将list集合的元素随机排放
//-----------------------------华丽的分割线------------------------------------
Arrays:
用于操作数组的工具类里面都是静态方法
详情请查看API问的 java util Arrays
asList:将数组变成list集合
把数组变成list集合有什么好处?
可以使用集合的思想和方法来操作数组中的元素。
注意:将数组变成集合,不可以使用集合的增删方法。
因为数组的长度是固定。
contains。
get
indexOf()
subList();
如果你增删。那么会反生UnsupportedOperationException,
String[] arr = {"abc","cc","kkkk"};
List<String> list = Arrays.asList(arr);
//sop("contains:"+list.contains("cc"));
//list.add("qq");//UnsupportedOperationException,
//sop(list);
//int[] nums = {2,4,5};
Integer[] nums = {2,4,5};
List<Integer> li = Arrays.asList(nums);
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
集合变数组:
Collection接口中的toArray方法
1.指定类型的数组到底是要定义多长呢?
当指定类型的数组长度小于集合的size.那么该方法内部会创建一个新的数组.长度为集合的size.
当指定类型的数据长度大于集合的size.就不会创建新的数组.而是使用传递进来的数组.
所以创建一个刚刚好的数组最优.
2.为什么要将集合变成数组呢?
为了限定对元素的操作,不需要进行增删了.
//-----------------------------华丽的分割线------------------------------------
高级for循环
格式:
for(数据类型 变量名 : 被遍历的集合(Collection)或者数组)
{
}
对集合进行遍历。
只能获取集合元素。但是不能对集合进行操作。
迭代器除了遍历,还可以进行remove集合中元素的动作。
如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
传统for和高级for有什么区别呢?
高级for有一个局限性。必须有被遍历的目标。
建议在遍历数组的时候,还是希望是用传统for。因为传统for可以定义脚标。
import java.util.*;
class ForEachDemo
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>();
al.add("abc1");
al.add("abc2");
al.add("abc3");
for(String s : al)
{
//s = "kk";
System.out.println(s);
}
System.out.println(al);
/*
Iterator<String> it = al.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
*/
int[] arr = {3,5,1};
for(int x=0; x<arr.length; x++)
{
System.out.println(arr[x]);
}
for(int i : arr)
{
System.out.println("i:"+i);
}
HashMap<Integer,String> hm = new HashMap<Integer,String>();
hm.put(1,"a");
hm.put(2,"b");
hm.put(3,"c");
Set<Integer> keySet = hm.keySet();
for(Integer i : keySet)
{
System.out.println(i+"::"+hm.get(i));
}
// Set<Map.Entry<Integer,String>> entrySet = hm.entrySet();
// for(Map.Entry<Integer,String> me : entrySet)
for(Map.Entry<Integer,String> me : hm.entrySet())
{
System.out.println(me.getKey()+"------"+me.getValue());
}
}
}
//-----------------------------华丽的分割线------------------------------------
JDK1.5版本出现的新特性。
方法的可变参数。
在使用时注意:可变参数一定要定义在参数列表最后面。
可变参数:
其实就是上一种数组参数的简写形式。
不用每一次都手动的建立数组对象。
只要将要操作的元素作为参数传递即可。
隐式将这些参数封装成了数组。
class ParamMethodDemo
{
public static void main(String[] args)
{
show("haha",2,3,4,5,6);
}
public static void show(String str,int... arr)
{
System.out.println(arr.length);
}
//-----------------------------华丽的分割线------------------------------------
静态导入。
import static
注意:
当类名重名时,需要指定具体的包名。
当方法重名是,指定具备所属的对象或者类。
import java.util.*;//导入util包中的所有的类
import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。