一、Map集合
Map<K,V>集合是一个接口,和List集合及Set集合不同的是,它是双列集合,并且可以给对象加上名字,即键(Key)
特点:
1、该集合存储键值对,一对一对往里存
2、要保证键的唯一性
Map集合的常用方法:
1、添加
V put(K key,V value);//添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。
void putAll(Map <? extends K,? extends V> m);//添加一个集合
2、删除
clear();//清空V remove(Object key);//删除指定键值对
3、判断
containsKey(Objectkey);//判断键是否存在
containsValue(Objectvalue)//判断值是否存在
isEmpty();//判断是否为空
4、获取
V get(Object key);//通过键获取对应的值
size();//获取集合的长度
Collection<V> value();//获取Map集合中所以得值,返回一个Collection集合
Set<Map.Entry<K,V>> entrySet();
Set<K> keySet();
注意:HashMap集合可以通过get()方法的返回值来判断一个键是否存在,通过返回null来判断。
Map集合的子类:
Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0,效率低。
HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。JDK1.2,效率高。
TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
Map和Set很像,其实Set底层就是使用了Map集合。
注意:HashMap保证元素唯一性的方法 是通过元素的两个方法,hashCode()和equals()来完成的,TreeMap保证元素唯一性的方法是compareTo()方法返回0。
Map集合的两种取出方式:
1、Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。所以可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
Map集合的取出原理:将map集合转成set集合。再通过迭代器取出。
2、Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
class HashMapTest {
public static void main(String[] args) {
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("A", "beijing");
hm.put("B", "sahnghai");
hm.put("C", "changsha");
hm.put("D", "tianjing");
keyset(hm);
entryset(hm);
}
// keySet取出方式
public static void keyset(HashMap<String, String> hm) {
Iterator<String> it = hm.keySet().iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
// keySet取出方式
public static void entryset(HashMap<String, String> hm) {
Iterator<Map.Entry<String, String>> it = hm.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
String s = entry.getKey();
String s2 = entry.getValue();
System.out.println(s + ":::" + s2);
}
}
}
Map是一个接口,其实,Entry也是一个接口,它是Map的子接口中的一个内部接口,就相当于是类中有内部类一样。
interface Map
{
public static interface Entry
{
public abstract Object getKey();
public abstract Object getValue();
}
}
class HashMap implements Map
{
class Hahs implements Map.Entry
{
public Object getKey(){}
public Object getValue(){}
}
}
为什么要定义在内部:因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。
Map扩展知识:
在很多项目中,应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。
/*
map扩展知识。
map集合被使用是因为具备映射关系。
*/
import java.util.*;
class MapExpandKnow {
public static void main(String[] args) {
// 预热班集合
HashMap<String, String> yureban = new HashMap<String, String>();
// 就业班集合
HashMap<String, String> jiuyeban = new HashMap<String, String>();
// 学校集合
HashMap<String, HashMap<String, String>> czbk = new HashMap<String, HashMap<String, String>>();
// 学校中班级集合和名称的映射
czbk.put("yureban", yureban);
czbk.put("jiuyueban", jiuyeban);
// 预热班级中学号与姓名的映射
yureban.put("01", "zhangsan");
yureban.put("02", "lisi");
// 就业班级中学号与姓名的映射
jiuyeban.put("01", "wangwu");
jiuyeban.put("02", "zhouqi");
// 直接显示全部学生信息
getAllStudentInfo(czbk);
}
// 定义一个方法获取全部学生信息,包括在哪个班级,叫什么名字,学号多少
public static void getAllStudentInfo(
HashMap<String, HashMap<String, String>> hm) {
for (Iterator<String> it = hm.keySet().iterator(); it.hasNext();)// 用keySet取出方式
{
String s = it.next();// 班级名称
System.out.println(s + ":");
HashMap<String, String> stu = hm.get(s);// 班级集合
getStudentInfo(stu);
}
}
// 获取班级中学生的信息,包括姓名和学号
public static void getStudentInfo(HashMap<String, String> hm) {
for (Iterator<String> it = hm.keySet().iterator(); it.hasNext();) {
String key = it.next();// 学号
String value = hm.get(key);// 姓名
System.out.println(key + "..." + value);
}
}
}
Collections是对集合框架的一个工具类。它里边的方法都是静态的,不需要创建对象。并未封装特有数据。
在Collections工具类中大部分方法是用于对List集合进行操作的,如比较,二分查找,随机排序等。
常见操作:
1、查找
T max(Collection<? extends T> coll);//根据集合的自然顺序,获取coll集合中的最大元素
T max(Collection<? extends T> coll,Comparator<? super T> comp);//根据指定比较器comp的顺序,获取coll集合中的最大元素
int binarySearch(Lsit<? extends Comparable<? super T>> list,Tkey);//二分法搜索list集合中的指定对象
2、替换
void fill(List<? super T> list, T obj);//将list集合中的全部元素替换成指定对象obj
boolean replaceAll(List<T> lsit,T oldVal,T newVal);//用newVal替换集合中的oldVal值
void swap(Listlist,int i,int j);/在指定列表的指定位置处交换元素
3、排序:
void shuffle(List<?> list);//使用默认随机源对list集合中的元素进行随机排序
void sort(Lsit<T> list);//根据自然顺序对list集合中的元素进行排序
void sort(List<T> lsit,Comparator<? super T> c);//根据指定比较器c的排序方式对list集合进行排序
4、反转
reverse(List<?> list);//反转list集合中元素的顺序
Comparator reverseOrder();//返回一个比较器,强行逆转了实现Comparable接口的对象的自然顺序
Comparator reverseOrder(Comparator<T> cmp);//返回一个比较器,强行逆转了指定比较器的顺序
5、同步的集合
List<T>synchronized List(List<T> list);//返回支持的同步(线程安全的)List集合
Map<K,V>synchronized List(Map<K,V> m);//返回支持的同步(线程安全的)Map集合
Collections和Collection的区别:
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口:
List:对元素都有定义索引。有序的。可以重复元素。
Set:不可以重复元素。无序
Collections是集合框架中的一个工具类。该类中的方法都是静态的。提供的方法中有可以对list集合进行排序,二分查找等方法
通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
/*
使用Collections中的方法fill对List集合中的部分元素进行替换
*/
import java.util.*;
public class TestDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("ab");
list.add("abcd");
list.add("a");
list.add("abcde");
try {
fillSome(list, 1, 5, "shenma");
} catch (Exception e) {
System.out.println(e.toString());
}
System.out.println(list);
}
// 替换部分元素方法
public static void fillSome(List<String> list, int start, int end, String s)
throws Exception {
if (start >= end)
throw new Exception("没有要替换的元素");// 如果输入的end小于或者等于start,则抛出异常
// 定义一个新集合
List<String> li = new ArrayList<String>();
// 因为每移除一次,后面的元素就会补上,所以这里用y来控制次数
for (int x = start, y = start; y < end; y++) {
li.add(list.get(x));// 将需要替换的元素增加到新集合
list.remove(x);// 移除需要替换的元素
}
Collections.fill(li, s);// 替换成需要的元素s
list.addAll(start, li);// 将替换的部分增加进原集合
}
}
三、Arrays集合工具类
Arrays是用于操作数组的工具类。里边的方法也全是静态的。不需要创建对象。
把数组变成List集合的好处:可以使用集合的思想和方法来操作数组中的元素。如:contains,get,indexOf,subList等方法。
常见方法:
1、Lsit<T> asList(T... a);//将数组转换为集合
注意:
1、将数组转换成集合,不可使用集合的增删方法,因为数组的长度是固定的。
2、如果数组中的元素都是对象,则变成集合时,数组中的元素就直接转为集合中的元素。
3、如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
2、binarySearch():二分查找方法,fill():替换方法,sort():排序方法等
特点:可对数组元素进行相应操作,可以接受除boolean之外的其他各种基本数据类型及有序的引用类型数组的参数,且还可以对指定元素的范围,并可根据指定比较器进行相应的操作。
3、String toString();//可以接收各种数组类型参数,并返回指定数组内容的字符串表现形式。
// Arrays操作数组的工具类
import java.util.Arrays;
import java.util.List;
public class ArraysDemo {
public static void main(String[] args) {
int[] attr = { 1, 2, 3, 4, 5 };
System.out.println(Arrays.toString(attr));
String[] strAttr = { "aaa", "bbb", "ccc" };
/*
* 将数组变成集合,不可以使用集合的增删方法,因为数组的长度是固定的
*/
List<String> list = Arrays.asList(strAttr);
// list.add("ddd"); error
System.out.println(list);
/*
* 注意: 如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素,
* 如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在
*/
int[] nums = { 1, 2, 3, 4, 5 };
List ls = Arrays.asList(nums);
// List<int[]> ls = Arrays.asList(nums);
System.out.println(ls);// 会输出数组的地址
}
}
集合变数组:
Collection接口中的toArray()方法;
1、指定类型的数组长度小于了集合的size,那么该方法内部会创建一个 新的数组,长度为集合的长度。
当指定类型的数组长度大于了集合的长度,就不会新创建数组,而是使用传递进来的数组,所以创建一个刚刚好的数组最优。
2、将集合变数组是为了限定对元素的操作。
扩展知识---1.5版本新特性:
1、高级for格式:for(数据类型变量名 :被遍历的集合(collection)或者数组) {执行语句}
2、方法的可变参数:public void param(int... args)
如果一个方法在参数列表中传入多个参数,个数不确定,那么每次都要复写该方法。这时可以用数组作为形式参数。但是在传入时,每次都需要定义一个数组对象,作为实际参数。在JDK1.5版本后,就提供了一个新特性:可变参数。
可变参数其实就是数组参数的简写形式。不用每一次都手动的建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成了数组。
3、静态导入
写法:
import staticjava.util.Arrays.*;//导入的是Arrays这个类中的所以静态成员。
import staticjava.lang.System.*//导入了Ssytem类中所以静态成员。
没加static导入的是类,加上static导入的全是某一个类中所以的静态成员。这样写在调用该类的静态方法时可以不用再写类名。如:Arrays.sort(数组);就可以直接写sort(数组);
注意:当导入的两个类中有同名成员时,需要在成员前加上相应的类名。
当类名重名时,需要指定具体的包名。当方法重名时,指定具体所属的对象或者类。