一,Map集合
1.概述:
- 该集合存储键值对。一次添加一对,而且要保证键的唯一性。
- 嵌套类摘要 static interface Map.Entry
2.常用方法:
2.1 添加
value put( key,value ):返回前一个和key关联的值,如果没有返回null。
说明:添加元素,如果出现相同的键,那么后添加的值会覆盖原有键对应的值,put方法会返回被覆盖的值
2.2 删除
- void clear():清空map集合。
- value remove(Object key):根据指定的key删除这个键值对。
2.3 判断
- boolean containsKey(key);
- boolean containsValue(value);
- boolean isEmpty();
2.4 获取
- value get(key):通过键获取值,如果没有该键返回null。当然可以通过返回null,来判断是否包含指定键。
- int size():获取键值对个数。
- Collection values() 返回此映射中包含的值的 Collection 视图。
- Set keySet() 返回此映射中包含的键的 Set 视图。
- Set
3. map集合的两种取出方式;
3.1 第一种:keySet()方法
- 原理:
- 通过keySet方法将map中所有的键存入到Set集合。因为set具备迭代器,所以可以迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。
- 代码示例:
import java.util.*;
class MapDemo {
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("001","A1");
map.put("003","C3");
map.put("002","B2");
map.put("004","D4");
//1.先获取map集合的所有键的Set集合,keySet();
Set<String> keySet=map.keySet();
//2.有了Set集合,就可以获取其迭代器。
Iterator<String> it = keySet.iterator();
while (it.hasNext()) {
String key=it.next();
//3.有了键值可以通过map集合的get方法获取对应的值。
String value=map.get(key);
System.out.println("key:"+key+"---value:"+value);
}
}
3.2 第二种:内部接口 Map.Entry
Entry是Map接口里面的一个内部接口,用于封装key- value,有3个方法:
a. Object getKey(); 返回Entry里包含的key值
b. Object getValue(); 返回Entry里包含的value值
c. Object setValue(Object value); 设置Entry里包含的value值,并返回新设置的value值;
原理:
- 通过entrySet()方法,将键和值的映射关系(映射关系的类型就是Map.Entry类型)作为对象存储到了Set集合中,调用Set的iterator方法,此时每个Iterator对象是Map.Entry对象,对Map.Entry分离出key - value。
代码示例(接):
Set<Map.Entry<String,String>> es = map.entrySet();
Iterator<Map.Entry<String,String>> it = es.iterator();
while (it.hasNext()){
Map.Entry<String,String> me=it.next();
String key = me.getKey();
String value = me.getValue();
System.out.println(key+"::"+value);
}
3.3 第三种:values()
- 原理:通过values方法将map集合的值存入Collection集合,再使用迭代器获取
- 代码示例(接):
Collection<String> values = map.values();
Iterator<String> it = values.iterator();
while(it.hasNext()){
System. out.println(it.next());
}
4. HashMap
4.1 特点:
判断键的唯一性的方式:以元素的Hashcode值和对象的equals方法判断键的唯一性。
代码示例:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/*
* 将学生对象(年龄和姓名)和学生的归属地通过键与值存储到map集合中
* 注意:姓名和年龄相同的视为同一个学生。
* 保证学生的唯一性。
*/
public class HashMapDemo {
public static void main(String[] args) {
HashMap<Student, String> hs = new HashMap<Student, String>();
System.out.println("HashMap集合存储元素调用haseCode和equals过程:");
hs.put(new Student("lishi01", 21), "beijing");
// 先判断hashCode的值,相等,再判断equals是否相等,相等则key重复,value将被会覆盖,即"beijing"被"tianjin"覆盖
hs.put(new Student("lishi01", 21), "tianjin");
hs.put(new Student("lishi02", 22), "shanghai");
hs.put(new Student("lishi03", 23), "nanjing");
//先判断hashCode的值,不相等,则key不同,向集合中存入该元素
hs.put(new Student("lishi01", 24), "wuhan");
System.out.println("------------------");
Iterator<Map.Entry<Student, String>> its = hs.entrySet().iterator();
while (its.hasNext()) {
Map.Entry<Student, String> es = its.next();
Student stu = es.getKey();
String addr = es.getValue();
System.out.println(stu + "......" + addr);
}
}
}
class Student {
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
//输出调用该方法对象的name
System.out.println(this.name+"...hashCode");
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
//输出调用该方法的对象与传入对象相比较的name
System.out.println(this.name+"...equals..."+((Student) obj).getName());
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// 转换成字符串
public String toString() {
return name + ":" + age;
}
}
运行结果:
如果希望输入的键值对集合按照跟原来存入的顺序一致,就使用LInkedHashMap
5. TreeMap:
5.1 特点:
- 给map集合中的键按自然顺序进行排序
- 判断键的唯一性的方式:就是根据保证元素唯一性的依据比较方法(实现Comparable接口中根据覆盖的compareTo方法返回值,实现Comparator接口中根据覆盖的compare方法)的返回结果是否是0,是0,就是相同元素,不存。
5.2 键值自定义排序:
- 两种方法,与TreeSet中的自定义一样
- 代码示例:
/*
*需求:对学生对象的年龄进行升序排列。
*因为数据是可以以键值对形式存在的。
*所以要使用可以排序的Map集合:TreeMap.
*/
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
TreeMap<Student, String> tm = new TreeMap<Student, String>(new StuNameComparator());
System.out.println("TreeMap集合储存元素,调用compare方法过程:");
tm.put(new Student("lishi02", 22), "shanghai");
tm.put(new Student("lishi01", 21), "beijing");
// 1.调用compare方法,先与集合中已存在的"lishi02"比较:key不同;
// 2.再与"lishi01"比较:name相同;然后再比较age:相同;则key相同;
// 3.将value进行覆盖:"beijing"被"tianjin"覆盖
tm.put(new Student("lishi01", 21), "tianjin");
tm.put(new Student("lishi03", 23), "nanjing");
// key不同,将不会覆盖
tm.put(new Student("lishi01", 24), "wuhan");
System.out.println("--------------------");
Iterator<Map.Entry<Student, String>> it = tm.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Student, String> me = it.next();
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu + "..." + addr);
}
}
}
// 采用第二种方式,进行键值排序:定义一个类实现Comparator接口,覆盖Compare方法
class StuNameComparator implements Comparator<Student> {
public int compare(Student s1, Student s2) {
System.out.println(s1.getName() + "..." + s2.getName());
int num = s1.getName().compareTo(s2.getName());
if (num == 0)
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
return num;
}
}
class Student {
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// 转换成字符串
public String toString() {
return name + ":" + age;
}
}
运行结果:
二,Collections工具类:
Collectons:是集合框架的工具类,位于java.util 包,完全由在 collection 上进行操作或返回,里面的方法都是静态的。
1. Collections和Collection的区别
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
- 它有两个常用的子接口(List:对元素都有定义索引,有序的,可以重复元素;Set:不可以重复元素。无序。)
Collections是集合框架中的一个工具类。该类中的方法都是静态的
- 提供的方法中有可以对list集合进行排序,二分查找等方法。
- 通常常用的集合都是线程不安全的。因为要提高效率。
- 如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
2. 常用方法:
2.1 排序:
static <T extends Comparable<? super T>> void sort(List<T> list)
:根据元素的自然顺序 对指定列表按升序进行排序。static <T> void **sort**(List<T> list, Comparator<? super T> c)
根据指定比较器产生的顺序对指定列表进行排序。
2.2 获取:
static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
:根据元素的自然顺序,返回给定 collection 的最大(最小为min)元素。static <T> T **max**(Collection<? extends T> coll, Comparator<? super T> comp)
:根据指定比较器产生的顺序,返回给定 collection 的最大(最小为min)元素。static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
:使用二分搜索法搜索指定列表,以获得指定对象。如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
使用二分搜索法搜索指定列表,以获得指定对象。
2.3 修改
static void swap(List<?> list, int i, int j)
在指定列表的指定位置处交换元素。static <T> boolean **replaceAll**(List<T> list, T oldVal, T newVal)
使用另一个值替换列表中出现的所有某一指定值。static <T> void **fill**(List<? super T> list, T obj)
使用指定元素替换指定列表中的所有元素。static void shuffle(List<?> list)
使用默认随机源对指定列表进行置换。
2.4 反转方法
static void reverse(List<?> list)
反转指定列表中元素的顺序。static <T> Comparator<T> reverseOrder()
返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
返回一个比较器,它强行逆转指定比较器的顺序。
2. 代码示例:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/*
* 需求:分别按自然顺序进行二分法查找,并打印索引,
* 按字符串长度进行二分法查找,并打印索引,并演示
* Collections的sort方法和binarySearch方法的实现过程。
*/
class CollectionsDemo {
public static void main(String[] args) {
binarySearchDemo();
}
public static void binarySearchDemo() {
List<String> list = new ArrayList<String>();
list.add("abcd");
list.add("aaa");
list.add("cc");
list.add("kkk");
list.add("qq");
list.add("z");
System.out.println("按自然顺序进行二分法查找,并打印索引结果示例:");
// 按自然顺序排序,并打印
Collections.sort(list);
System.out.println(list);
// 按自然顺序进行二分法查找,并打印索引
// int index =Collections.binarySearch(list,"cc");//
int index = halfSearch(list, "ccc");
System.out.println("index=" + index);
System.out.println("");
System.out.println("按字符串长度进行二分法查找,并打印索引结果示例:");
// 按字符串长度排序,并打印
//Collections.sort(list, new StrLenComparator());//根据指定比较器产生的顺序(字符串长度)对指定列表进行排序
//自定义按字符串长度排序方法
mySort(list,new StrLenComparator());
System.out.println(list);
// 按指定的比较器(按字符串长度)对列表进行二分法查找,并打印索引
// int lenIndex =Collections.binarySearch(list,"cc",new StrLenComparator());
//自定义按字符串长度进行二分法查找,并打印索引
int lenIndex = halfSearch2(list, "ccc", new StrLenComparator());
System.out.println("lenIndex=" + lenIndex);
}
public static <T> void mySort(List<T> list,Comparator<? super T> comp) {
for(int i = 0; i < list.size() - 1; i++){
for(int j = i + 1; j < list.size(); j++){
if(comp.compare(list.get(i),list.get(j))>0){
Collections. swap(list ,i,j);
}
}
}
}
public static int halfSearch(List<String> list, String key) {
int max, min, mid;
max = list.size() - 1;
min = 0;
while (min <= max) {
mid = (min + max) >> 1;
String str = list.get(mid);
int num = str.compareTo(key);
if (num > 0)
max = mid - 1;
else if (num < 0)
min = mid + 1;
else
return mid;
}
return -min - 1; //模拟返回值:-(插入点) - 1
}
public static int halfSearch2(List<String> list, String key,
Comparator<String> cmp) {
int max, min, mid;
max = list.size() - 1;
min = 0;
while (min <= max) {
mid = (min + max) >> 1;
String str = list.get(mid);
int num = cmp.compare(str, key);
if (num > 0)
max = mid - 1;
else if (num < 0)
min = mid + 1;
else
return mid;
}
return -min - 1; //模拟返回值:-(插入点) - 1
}
}
// 采用比较器,根据字符串长度进行排序,若长度相等,则安自然排序
class StrLenComparator implements Comparator<String> {
public int compare(String s1, String s2) {
if (s1.length() > s2.length())
return 1;
if (s1.length() < s2.length())
return -1;
return s1.compareTo(s2);
}
}
运行结果:
三,Arrays工具类:
Arrays是集合框架中的工具类,里面的方法都是静态的,包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。
1. 数组和集合的互转:
1.1 数组转集合;
- static List asList(T… a) 返回一个受指定数组支持的固定大小的列表。 可以使用集合的方法操作数组。
注意:数组的长度是固定的,所以对于结合的增删方法是不可以使用的,否则,会发生UnsupportedOperationException。
- 如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
- 如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储。
int[] arr1 = {31,11,51,61};
List< int[]> list1 = Arrays.asList(arr1);
System.out.println(list1); //[[I@19bb25a]
Integer[] arr2 = {31,11,51,61};
List list2 = Arrays.asList(arr2);
System.out.println(list2); //[31, 11, 51, 61]
1.2 集合转数组:
- 使用Collection接口中的toArray方法,可以对集合中的元素操作的方法进行限定,不允许对其进行增删
- 需要传入一个指定类型的数组
- 长度定义:
- 如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同的size的数组。
- 如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为null。
- 所以建议,最后长度就指定为,集合的size。