Map集合
Map:一次添加一对元素。Collection 一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实map集合中存储的就是键值对。
map集合中必须保证键的唯一性。
Map常用方法:
添加。
value put(key,value):返回前一个和key关联的值,如果没有返回null.
删除。
void clear():清空map集合。
value remove(key):根据指定的key翻出这个键值对。判断。
boolean containsKey(key):
boolean containsValue(value):
boolean isEmpty();获取。
value get(key):通过键获取值,如果没有该键返回null。
当然可以通过返回null,来判断是否包含指定键。
int size(): 获取键值对的个数。
Map常用的子类:
|--Hashtable :内部结构是哈希表,是同步的。不允许null作为键,null作为值。
|--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|--HashMap : 内部结构是哈希表,不是同步的。允许null作为键,null作为值。
|--TreeMap : 内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。
Map集合的两种取出方式:
- Set keySet:将Map中所有的键存入Set集合。因为Set具备迭代器。所有可以迭代的方式取出所有的键,再根据get方法,获取每一个键对应的值。
Map集合取出的原理:将map集合转成Set集合,再通过迭代器取出。
- Set
Map的综合应用
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 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;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public String toString(){
return name+"---"+age;
}
public int hashCode(){
return name.hashCode()+34*age;
}
public boolean equals(Object obj){
if(!(obj instanceof Student))
throw new ClassCastException("class erro");
Student s=(Student)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
}
class StuNameComparator implements Comparator<Student>{
public int compare(Student s1,Student s2){
int num=s1.getName().compareTo(s2.getName());
return num==0?new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())):num;
}
}
class MapTest
{
public static void main(String[] args)
{
/*
//HashMap第一种取出方式keySet
HashMap<Student,String>hm=new HashMap<Student,String>();
hm.put(new Student("lisi1",21),"beijin");
hm.put(new Student("lisi2",22),"shanghai");
hm.put(new Student("lisi3",23),"nanjing");
hm.put(new Student("lisi4",24),"dalian");
Set<Student>keySet=hm.keySet();
Iterator<Student>it=keySet.iterator();
while(it.hasNext()){
Student stu=it.next();
String addr=hm.get(stu);
System.out.println(stu+"---"+addr);
}
//HashMap第二种取出方式Map.Entry
Iterator<Map.Entry<Student,String>>iter=hm.entrySet().iterator();
while(iter.hasNext()){
Map.Entry<Student,String> me=iter.next();
String addr=me.getValue();
Student stu=me.getKey();
System.out.println(stu+"....."+addr);
}*/
//TreeMap取出方式
TreeMap<Student,String>tm=new TreeMap<Student,String>(new StuNameComparator());
tm.put(new Student("slisi1",21),"beijin");
tm.put(new Student("wlisi2",22),"shanghai");
tm.put(new Student("flisi3",23),"nanjing");
tm.put(new Student("alisi4",24),"dalian");
//高级for循环迭代方式
/*for(Map.Entry<Student,String> me:tm.entrySet())
System.out.println(me.getKey()+"-----"+me.getValue);*/
Iterator<Map.Entry<Student,String>>it=tm.entrySet().iterator();
while(it.hasNext()){
Map.Entry<Student,String> me=it.next();
Student s=me.getKey();
String addr=me.getValue();
System.out.println(s+"-----"+addr);
}
}
}
===========================================================
集合的一些技巧:
需要唯一吗?需要:Set
需要制定顺序:
需要: TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList
如何记录每一个容器的结构和所属体系呢?
看名字!
List
|--ArrayList
|--LinkedList
Set
|--HashSet
|--TreeSet
后缀名就是该集合所属的体系。 前缀名就是该集合的数据结构。 看到array:就要想到数组,就要想到查询快,有角标. 看到link:就要想到链表,就要想到增删快,就要想要 add get remove+frist last的方法 看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法。 看到tree:就要想到二叉树,就要想要排序,就要想到两个接口Comparable,Comparator 。 而且通常这些常用的集合容器都是不同步的。 ============================================
Map集合和Collection集合的区别?
- Map中一次存储是键值对。
Collection中一次存储是单个元素。 -
Map的存储使用的put方法。
Collection存储使用的是add方法。 -
Map的取出,是讲Map转成Set,在使用迭代器取出。
Collection取出,使用就是迭代器。 -
如果对象很多,必须使用容器存储。
如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,
如果没有映射关系,可以使用Collection存储。
Collections和Arrays
Collections和Arrays:是集合框架的工具类。里面的方法都是静态的。
static void shuffle(List<?> list)
使用默认随机源对指定列表进行置换。
static <T> T
max(Collection<? extends T> coll, Comparator<? super T> comp)
根据指定比较器产生的顺序,返回给定 collection 的最大元素。
static <T> int
binarySearch(List<? extends Comparable<? super T>> list, T key)
使用二分搜索法搜索指定列表,以获得指定对象。
static <T> int
binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
使用二分搜索法搜索指定列表,以获得指定对象。
static <T> Comparator<T>
reverseOrder()
返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。
static <T> Comparator<T>
reverseOrder(Comparator<T> cmp)
返回一个比较器,它强行逆转指定比较器的顺序。
static <T> boolean
replaceAll(List<T> list, T oldVal, T newVal)
使用另一个值替换列表中出现的所有某一指定值。
static void reverse(List<?> list)
反转指定列表中元素的顺序。
static <T extends Comparable<? super T>>
void
sort(List<T> list)
根据元素的自然顺序 对指定列表按升序进行排序。
static <T> void
sort(List<T> list, Comparator<? super T> c)
根据指定比较器产生的顺序对指定列表进行排序。
static void swap(List<?> list, int i, int j)
在指定列表的指定位置处交换元素。
static <T> List<T>
synchronizedList(List<T> list)
返回指定列表支持的同步(线程安全的)列表。
Collections方法使用部分代码:
public static void demo_4() {
List<String> list = new ArrayList<String>();
list.add("abcde");
list.add("cba");
list.add("zhangsan");
list.add("zhaoliu");
list.add("xiaoqiang");
System.out.println(list);
// Collections.replaceAll(list, "cba", "nba"); // set(indexOf("cba"),"nba");
Collections.shuffle(list);//随机顺序
// Collections.fill(list, "cc");//填充
// String max = Collections.max(list,new ComparatorByLength());//最大值
// Collections.sort(list,new ComparatorByLength());//实现Comparator接口排序
System.out.println(list);
}
public static void demo_3() {
/*
TreeSet<String> ts = new TreeSet<String>(new Comparator<String>(){
@Override
public int compare(String o1, String o2) {
int temp = o2.compareTo(o1);
return temp;
}
});
*/
TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));
ts.add("abc");
ts.add("hahaha");
ts.add("zzz");
ts.add("aa");
ts.add("cba");
System.out.println(ts);
}
foreach语句:
格式:
for(类型 变量 :Collection集合|数组)
{
作用语句;
}
可以使用高级for遍历map集合吗?
不能直接用,但是可以将map转成单列的set,就可以用了。
Map
传统for和高级for的区别?
传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。
高级for是一种简化形式。它必须有被遍历的目标。
该目标要是数组,要么是Collection单列集合。
对数数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。
如果要对数组的角标进行操作建议使用传统for。
Array和集合的互相转换
集合转成数组
使用的就是Collection接口中的toArray方法。
toArray方法需要传入一个指定类型的数组。
为什么要转成数组(好处):
可以对集合中的元素操作的方法进行限定。不允许对其进行增删。
长度该如何定义呢?
如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。
如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为null。
所以建议,最后长度就指定为,集合的size。
List<String> list = new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
String[] arr = list.toArray(new String[list.size()]);
System.out.println(Arrays.toString(arr));
数组转成集合
使用Arrays:List asList(数组)将数组转成集合。
如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
String[] arr = {"abc","haha","xixi"};
List<String> list = Arrays.asList(arr);
如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储。
int[] arr = {31,11,51,61};
List<int[]> list = Arrays.asList(arr);
好处:其实可以使用集合的方法操作数组中的元素。
注意:数组的长度是固定的,所以对于集合的增删方法是不可以使用的,否则会发生UnsupportedOperationException
String[] arr = {"abc","haha","xixi"};
List<String> list = Arrays.asList(arr);
boolean b1 = list.contains("xixi");
// list.add("hiahia");//UnsupportedOperationException
函数的可变参数
其实就是一个数组,但是接收的是数组的元素。
自动将这些元素封装成数组。简化了调用者的书写。
注意:可变参数类型,必须定义在参数列表的结尾。
public void static main(){
show(1,2,3);
show(1,2,3,3,4,5,6);
print("saldklaskd",2,3,54,5,6,6,7);
}
public void show(int... arr)
{
System.out.println(arr.length());
}
public void print(String str,integer... arr)
{
System.out.println(arr.length());
}
静态导入
import static java.util.Collections.*;//静态导入,其实到入的是类中的静态成员。
import static java.util.Arrays.*
import static java.lang.System.*;
导入之后便可直接使用类中的静态函数,简化了书写
int[] arr={1,2,3,4};
sort(arr);//省略了Arrays.
out.println(Arrays.toString(arr));//省略了System.不能省略toString前面的Arrays,
//因为Object类中也有toString方法必须加上类名区分。