第十九天 集合-Map接口&容器工具类&集合框架总结【面试+工作】
第19天 集合
Map集合的特点,如是否可重复,是否有序仅作用在键上,如HashMap集合的键不得重复,值可以重复。
我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下图。
通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。
Map(HashMap)的使用:创建对象时加入两个泛型。
Map<k,v>
key - 此映射所维护的键的类型
value - 映射值的类型
使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中;
使用put方法时,若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。
Map接口的方法演示
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map<String, String> map = new HashMap<String,String>();
//给map中添加元素
map.put("星期一", "Monday");
map.put("星期日", "Sunday");
System.out.println(map); // {星期日=Sunday, 星期一=Monday}
//当给Map中添加元素,会返回key对应的原来的value值,若key没有对应的值,返回null
System.out.println(map.put("星期一", "Mon")); // Monday
System.out.println(map); // {星期日=Sunday, 星期一=Mon}
//根据指定的key获取对应的value
String en = map.get("星期日");
System.out.println(en); // Sunday
//根据key删除元素,会返回key对应的value值
String value = map.remove("星期日");
System.out.println(value); // Sunday
System.out.println(map); // {星期一=Mon}
}
}
put方法:
import java.util.HashMap;
/*
* Map 地图 . 映射 .
*
* 一个对一个.
* Map 双列集合. Key 键, Value值 . 一个键对应一个值.
*
* 保存元素 :
* 1.key -values
* 2.键是唯一.值随意.
* 3.如果键重复,老值会被新值替换,作为返回值返回.
*/
public class Demo {
public static void main(String[] args) {
//创建 HashMap 对象
HashMap<String,String > hashMap = new HashMap<>();
//添加 元素 put 方法
hashMap.put("大郎", "金莲"); //{大郎=金莲}
hashMap.put("西门", "金莲"); //{西门=金莲, 大郎=金莲}
hashMap.put("老王", "柳岩");
String put = hashMap.put("老王", "武松"); // 如果键 重复了, 值会被替换.
System.out.println(put);
System.out.println(hashMap);
}
}
get方法:
import java.util.HashMap;
/*
* 获取 元素. 通过 键 获取值.
*
* V get (key) .
*/
public class Demo2 {
public static void main(String[] args) {
// 创建 HashMap 对象
HashMap<String, String> hashMap = new HashMap<>();
// 添加 元素 put 方法
hashMap.put("大郎", "金莲"); // {大郎=金莲}
hashMap.put("西门", "金莲"); // {西门=金莲, 大郎=金莲}
hashMap.put("老王", "柳岩");
String value = hashMap.get("老王");
System.out.println(value);
String value2 = hashMap.get("大郎");
System.out.println(value2);
String value3 = hashMap.get("西门");
System.out.println(value3);
}
}
import java.util.HashMap;
/*
* 其他方法
void clear() 从此映射中移除所有映射关系(可选操作)。
boolean containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。
boolean isEmpty() 如果此映射未包含键-值映射关系,则返回 true。
V remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
int size() 返回此映射中的键-值映射关系数。
*/
public class Demo {
public static void main(String[] args) {
//创建 HashMap
HashMap<String,String > hashMap = new HashMap<>();
// 保存角色名字和书名.
hashMap.put("东方不败", "<<笑傲江湖>>");
hashMap.put("岳不群", "<<笑傲江湖>>");
hashMap.put("林平之", "<<笑傲江湖>>");
hashMap.put("乔峰", "<<天龙八部>>");
hashMap.put("段誉", "<<天龙八部>>");
hashMap.put("虚竹", "<<天龙八部>>");
System.out.println(hashMap.containsKey("乔峰"));
System.out.println(hashMap.containsKey("梅超风"));
System.out.println("=======");
System.out.println(hashMap.isEmpty());
//hashMap.clear();
// System.out.println(hashMap);
String remove = hashMap.remove("乔峰");
System.out.println(remove);
System.out.println(hashMap);
}
}
Collection<V> values() //返回所有值的集合
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
/*
* 遍历方式1 : 通过键的集合,获取值 .
* 演示方法 Collection<V> values() //返回所有值的集合
*/
public class Demo3 {
public static void main(String[] args) {
// 创建 HashMap 对象
HashMap<String, String> hashMap = new HashMap<>();
// 添加 元素 put 方法
hashMap.put("大郎", "金莲"); // {大郎=金莲}
hashMap.put("西门", "金莲"); // {西门=金莲, 大郎=金莲}
hashMap.put("老王", "柳岩");
Set<String> keySet = hashMap.keySet();
for (String key : keySet) {
String value = hashMap.get(key); // 通过 键 获取值
System.out.println(key + " -- " + value);
}
// 打印所有的值
Collection<String> values = hashMap.values(); // 应用不多 .
for (String v : values) {
System.out.println(v);
}
}
}
键找值方式:即通过元素中的键,获取键所对应的值
操作步骤与图解:
1.获取Map集合中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键
2.遍历键的Set集合,得到每一个键
3.根据键,获取键所对应的值
代码演示:
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map<String, String> map = new HashMap<String,String>();
//给map中添加元素
map.put("邓超", "孙俪");
map.put("李晨", "范冰冰");
map.put("刘德华", "柳岩");
//获取Map中的所有key
Set<String> keySet = map.keySet();
//遍历存放所有key的Set集合
Iterator<String> it =keySet.iterator();
while(it.hasNext()){
//得到每一个key
String key = it.next();
//通过key获取对应的value
String value = map.get(key);
System.out.println(key+"="+value);
}
}
}
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
/*
* 遍历方式1 : 通过键的集合,获取值 .
* 演示方法 Collection<V> values() //返回所有值的集合
*/
public class Demo3 {
public static void main(String[] args) {
// 创建 HashMap 对象
HashMap<String, String> hashMap = new HashMap<>();
// 添加 元素 put 方法
hashMap.put("大郎", "金莲"); // {大郎=金莲}
hashMap.put("西门", "金莲"); // {西门=金莲, 大郎=金莲}
hashMap.put("老王", "柳岩");
Set<String> keySet = hashMap.keySet();
for (String key : keySet) {
String value = hashMap.get(key); // 通过 键 获取值
System.out.println(key + " -- " + value);
}
fun1(hashMap);
// 打印所有的值
//Collection<String> values = hashMap.values(); // 应用不多 .
for (String v : values) {
System.out.println(v);
}
}
private static void fun1(HashMap<String, String> hashMap) {
// 获取所有的key
Set<String> keySet = hashMap.keySet();
for (String key : keySet) {
String value = hashMap.get(key); // 通过 键 获取值
System.out.println(key + " -- " + value);
}
}
}
/*
* 菜品类. 名字 ,价格, id. corsh 顶配的类.
*/
public class Cai {
private String name; // 菜名
private double price ;//价格
private String id ; // 菜id . 001
public Cai() {
super();
}
public Cai(String name, double price, String id) {
super();
this.name = name;
this.price = price;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return id + "--[" + name +":"+ price+"]" ;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
long temp;
temp = Double.doubleToLongBits(price);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Cai other = (Cai) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (Double.doubleToLongBits(price) != Double.doubleToLongBits(other.price))
return false;
return true;
}
}
import java.util.HashMap;
import java.util.Set;
/*
* map保存 元素, 键 String id , 值 Cai 对象 .
*/
public class Demo4 {
public static void main(String[] args) {
//创建map
HashMap<String,Cai> hashMap = new HashMap<>();
//创建 菜对象
Cai cai = new Cai("香菇油菜", 8.8, "001");
Cai cai2 = new Cai("耗油西红柿鸡蛋豆腐",28.8, "002");
Cai cai3 = new Cai("醋溜白菜",18.8, "003");
Cai cai4 = new Cai("皮蛋豆腐",28.8, "004");
//添加元素
hashMap.put("001", cai);
hashMap.put("002", cai2);
hashMap.put("003", cai3);
hashMap.put("004", cai4);
System.out.println(hashMap);
// 遍历map
Set<String> keySet = hashMap.keySet();
for (String key : keySet) {
Cai c = hashMap.get(key);
System.out.println(key +" -- "+ c.getName() +":"+c.getPrice());
}
}
}
在Map类设计时,提供了一个嵌套接口:Entry。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。
键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。
操作步骤与图解:
1.获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。
2.遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象
3.通过键值对(Entry)对象,获取Entry对象中的键与值。
public class MapDemo {
public static void main(String[] args) {
//创建Map对象
Map<String, String> map = new HashMap<String,String>();
//给map中添加元素
map.put("邓超", "孙俪");
map.put("李晨", "范冰冰");
map.put("刘德华", "柳岩");
//获取Map中的所有key与value的对应关系
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//遍历Set集合
Iterator<Map.Entry<String,String>> it =entrySet.iterator();
while(it.hasNext()){
//得到每一对对应关系
Map.Entry<String,String> entry = it.next();
//通过每一对对应关系获取对应的key
String key = entry.getKey();
//通过每一对对应关系获取对应的value
String value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
注意:Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了。
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
/*
* 遍历方式2: 拿一对. Entry 一个Entry 包含一对儿元素.
* getKey:获取键
* getValue : 获取值
*/
public class Demo {
public static void main(String[] args) {
//创建 HashMap
HashMap<String,String > hashMap = new HashMap<>();
// 保存角色名字和书名.
hashMap.put("东方不败", "<<笑傲江湖>>");
hashMap.put("岳不群", "<<笑傲江湖>>");
hashMap.put("林平之", "<<笑傲江湖>>");
hashMap.put("乔峰", "<<天龙八部>>");
hashMap.put("段誉", "<<天龙八部>>");
hashMap.put("虚竹", "<<天龙八部>>");
// 第二种方式遍历map
// a.获取 键值对 对象的集合 , entrySet .
Set<Entry<String,String>> entrySet = hashMap.entrySet();
// b.通过 entry 的方法, 获取键, 和 值
for (Entry<String, String> entry : entrySet) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key +" -- "+ value);
}
}
}
练习:每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。
注意,学生姓名相同并且年龄相同视为同一名学生。
public class Student {
private String name;
private int age;
//编写构造方法,文档中已省略
//编写get,set方法,文档中已省略
//编写toString方法,文档中已省略
}
public class HashMapTest {
public static void main(String[] args) {
//1,创建hashmap集合对象。
Map<Student,String> map = new HashMap<Student,String>();
//2,添加元素。
map.put(new Student("lisi",28), "上海");
map.put(new Student("wangwu",22), "北京");
map.put(new Student("zhaoliu",24), "成都");
map.put(new Student("zhouqi",25), "广州");
map.put(new Student("wangwu",22), "南京");
//3,取出元素。键找值方式
Set<Student> keySet = map.keySet();
for(Student key : keySet){
String value = map.get(key);
System.out.println(key.toString()+"....."+value);
}
//取出元素。键值对方式
Set<Map.Entry<Student, String>> entrySet = map.entrySet();
for (Map.Entry<Student, String> entry : entrySet) {
Student key = entry.getKey();
String value = entry.getValue();
System.out.println(key.toString()+"....."+value);
}
}
}
Collections是集合工具类,专门对集合进行操作。常用方法:
//排序前元素list集合元素 [33,11,77,55]
Collections.sort( list );
//排序后元素list集合元素 [11,33,55,77]
//list集合元素 [11,33,55,77]
Collections.shuffle( list );
//使用shuffle方法后,集合中的元素为[77,33,11,55],每次执行该方法,集合中存储的元素位置都会随机打乱
Arrays是数组工具类,常用方法:
public static int binarySearch(Xxx[] a,Xxx key) //查找元素索引
public static void sort(Xxx[] a) //排序
public static String toString(Xxx[] a) //返回字符串内容
集合ArrayList转为数组的方法为ArrayList的以下两个方法:
public Object[] toArray() //集合转数组
public <T> T[] toArray(T[] a)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/*
* Collections 和 Arrays
*/
public class Demo {
public static void main(String[] args) {
// fun();
//fun2();
//fun3(arrayList);
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(255);
arrayList.add(5);
arrayList.add(5);
arrayList.add(5);
arrayList.add(5);
arrayList.add(15);
arrayList.add(200);
Object[] array = arrayList.toArray();
System.out.println(array);
String string = Arrays.toString(array);
System.out.println(string);
}
private static void fun3(ArrayList<Integer> arrayList) {
Collections.sort(arrayList);
System.out.println(arrayList);
int binarySearch = Collections.binarySearch(arrayList, 15);
System.out.println(binarySearch);
}
private static void fun2() {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("5");
arrayList.add("255");
arrayList.add("15");
arrayList.add("200");
System.out.println(arrayList);
Collections.sort(arrayList);
System.out.println(arrayList);
}
private static void fun() {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(5);
arrayList.add(255);
arrayList.add(15);
arrayList.add(200);
System.out.println(arrayList);
Collections.sort(arrayList);
System.out.println(arrayList);
}
}
在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格式:
修饰符 返回值类型 方法名(参数类型... 形参名){ }
其实这个书写完全等价与
修饰符 返回值类型 方法名(参数类型[] 形参名){ }
只是后面这种定义,在调用时必须传递数组,而前者可以直接传递数据即可。
jdk1.5以后。出现了简化操作。... 用在参数上,称之为可变参数。
同样是代表数组,但是在调用这个带有可变参数的方法时,不用创建数组(这就是简单之处),直接将数组中的元素作为实际参数进行传递,其实编译成的class文件,将这些元素先封装到一个数组中,在进行传递。这些动作都在编译.class文件时,自动完成了。
代码演示:
public class ParamDemo {
public static void main(String[] args) {
int[] arr = {21,89,32};
int sum = add(arr);
System.out.println(sum);
sum = add(21,89,32);//可变参数调用形式
System.out.println(sum);
}
//JDK1.5之后写法
public static int add(int...arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
//原始写法
/*
public static int add(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
*/
}
注意:如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末尾位置。可变参数方法本质是数组,所以不可以与数组类型参数重载。
public class Demo2 {
public static void main(String[] args) {
// int add = add(10,20);
// System.out.println(add);
// int add2 = add(10,20,30);
//
int add3 = add(10,20,30 , 100,200,300 );
System.out.println(add3);
}
// public static int add(int i,int j){
// return i + j;
// }
// public static int add(int i,int j , int h ){
// return i + j + h ;
// }
//
// public static int add(int i,int j ,int h , int g ){
// return i + j + h + g;
// }
public static int add(int a ,int... x){
System.out.println("可变参数方法 ");
System.out.println(a);
// x 就是 一个数组.
System.out.println(x[0]);
for (int i = 0; i < x.length; i++) {
a +=x[i] ;
}
return a;
}
}
在导包的过程中我们可以直接导入静态部分,这样某个类的静态成员就可以直接使用了。在源码中经常会出现静态导入,而在日常开发中几乎没有人使用。
静态导入格式:
import static XXX.YYY; 导入后YYY可直接使用。
import java.util.ArrayList;
import java.util.Collections;
import static java.util.Collections.shuffle;
/*
* 静态导入
* 在导包的过程中我们可以直接导入静态部分,这样某个类的静态成员就可以直接使用了。
* 在源码中经常会出现静态导入,而在日常开发中几乎没有人使用。
* 静态导入格式:
* import static XXX.YYY; 导入后YYY可直接使用。
*/
public class Demo3 {
public static void main(String[] args) {
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add("7");
arrayList.add("8");
arrayList.add("9");
arrayList.add("17");
System.out.println(arrayList);
shuffle(arrayList);
System.out.println(arrayList);
}
public static void shuffle( ArrayList<Object> al){
System.out.println("自己的 ");
}
}
List:里面对象全部是有序的(通过三种方法来遍历) ArrayList,LinkedList,Vertor
常用方法: 增:add(4) 对象 位置+对象 集合 集合+位置。 删:remove(2)下标删对象,直接删对象。 改:set(1) 下标 对象。 查:get() 下标得对象, indexOf()对象得下标。
contains()必须是同一个对象才返回true iterator() size()。
常用方法: 增:add(4) 对象 位置,对象 集合 位置,集合 +2(对象) 新增:addFirst() addLast()。 删:remove(2)下标删对象,直接删对象 +2(对象) 新增:removeFirst() removeLast()。 改:set(1) 下标 对象 查:get() 下标得对象 indexOf()对象得下标 +2(对象) 新增:getFirst() getLast()。
contains() iterator()size()。
常用方法: 增:add(4) 对象 位置,对象 集合 位置,集合 addElement(对象) insertElement(对象)。 删:remove(2)下标删对象,直接删对象 removeElement(对象) removeAllElment()。 改:set(1) 下标,对象 setElementAt(对象,下标)。 查:get() 下标得对象 indexOf()对象得下标。
contains() iterator() size()。
iterator() :hasNext()判断有没有下一个元素。 next()获取下一个元素。 remove()在迭代器中移除元素。
不允许出现重复的方法,允许有一个null值,都没有顺序索引(通过增强for循环和迭代来遍历),所以查不了,改不了。 要想存入Set,必须重写equals()和hashCode()方法(String已经重写),两者返回值都为真表明相等,比的是内容。 其实一个equals()就可以,但是当存入数据量大的时候,一一比较效率非常低,加入hashCode,就是来判断不是同一个对象的。 用hashCode()无法判断是同一个对象。
因为所有的已经存入的对象保存在一个table里面,比较的效率非常高。 如果已存在,是不能再往里面添加(而Map是后面覆盖前面)。
内部维护的是HashMap的一个实例,存的是key的集合。 元素的表现是无序的,但一旦添加完元素,元素位置是固定的(也就是说你无论再运行多少遍,这个显示的顺序都一样),再添加新元素,不会影响前面元素的位置,给添加的元素分配位置,只要不打乱前面的元素位置,前面的元素位置就不会再发生变化。
常用方法: 增:add(对象)。 删:clear()移除所有对象 ,remove(对象)。 改:没有,没下标。 查:除了遍历出所有,没有,因为没有下标。 contains()内容相同就返回true iterator() size()
HashSet的子类,只有四个新增的构造器,没有其他新增方法,内部维护的是LinkedHashMap的一个实例,是双向链表结构。 元素存放顺序和迭代顺序一样(按顺序)。 常用方法同HashSet。
确保元素处于排序状态,底层为树结构。使用它可以从Set中提取有序的序列。
两种排序方法:自然排序和定制排序,默认采用自然排序。 自然排序:会调用集合元素的comparaTo(对象)方法来比较元素之间的大小关系,然后把集合按升序排列(实现 Comparable接口)。 定制排序:通过Comparator(比较器)接口,需要重写compara(对象,对象),要实现定制排序,需要把comparator实例作为形 参传给TreeSet的构造器。 要想把元素放到TreeSet中,必须实现Comparable接口,同时必须实现comparaTo方法。 或者继承Comparator接口,然后重写compara方法。 first() last()lower(对象) heigher(对象) 其他视图方法。
维护"键值对"的关联性 key,value 必须都为引用类型数据 key不可以重复(后覆盖先),保存在Set集合中(因为Set集合里面的元素不能重复,所以,,还必须重写equals和hashCode()方法),经常用String,因为都已经实现 put(key,value) remove(key) putAll(Map map) clear()清除所有 。(基本全是通过Set,也就是key,唯一性)。
获取key的集合: Set<> set= map.keySet();Iterator<> it=set.iterator();get(key) 迭代器。
获取value的集合: Collection values() 迭代器,增强for都可以。
Entry集合: Set<Entry<,>> entrys = map.entrySet(); for(Entry<String,String> entry : entrys)迭代器,增强for都可以 get(key) containsKey(key) containsValue(value) size isEmpty() equals()比较的当然是内容啦
允许key和value的值为null。 表现是无序的 比较key相等和Set一样。 LinkedHashMap:子类,有序的(等同上面的HashSet和LinkedHashSet)只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。
有序。 基于红黑树数据结构的实现。查看"键"或"键值对"时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
最古老,不允许key和value值为null
是HashTable的子类,用来处理文件的属性。 文件属性必须是key_value,必须都是字符串,存取数据用put(key,value),get(key)。
集合操作类 排序: Collections.reverse(list) 反序 Collections.shuffle()随机 Collections.sort()自然顺序升序 Collections.swap(对象,位置,位置)交换 查找: max() min()frequency(Collections,对象); copy(目标list,srclist) Collections.repalceAll(list,old对象,new对象)
synchronizedXXX(); synchronizedList(list)
1.线程安全的是vertor和HashTable。 2. List:允许重复的,全部有序(允许null)。 3.Set: HashSet无序的表现(一个null),其中HashSet的子类LinkedHashSet有序,TreeSet有序。 4.Map:HashMap无序的表现(一次null),其中HashMap的子类LinkedHashMap有序,TreeMap有序,HashTable无序(不能为null)。
5.ArrayList:查询效率高,增删效率低。 6.LinkedList:查询效率低,增删效率高。 7.Vertor:执行效率非常低。
8.HashSet:良好的增删查询性能。 9.LinkedHashSet:查询效率低,插入效率比HashSet低。
10.Map对象高于List。因为Map除了Value外还需要一个Object的Key,从而增大了Map的容量。
11. HashSet,HashMap的元素都是无序的,而他们的子类都是有序的,双向链表,非常类似,因为HashMap中的唯一的约束就是key,而 key恰恰是被HashMap维护的 12.TreeSet和TreeMap都是有序的,两个很类似。
13. 如果Map知道了Key,List知道了index,其性能在一百万条数据中无多大差别。
14.List按对象进入的顺序保存对象,不做排序或编辑操作。Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于 Set,而不关心它的序否则应该使用List)。Map同样对每个元素保存一份,但这是基于"键"的,Map也有内置的排序,因而不关心元素添加的 顺序。如果添加元素的顺序对你很重要,应该使LinkedHashSet或者LinkedHashMap。
15.HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显着提高性能。
数据结构指的数据存储和组织方式,如日常的容器中,有方形、圆形、存放液体、固体,都是。
我们在前边见到了多种不同结构的集合,每种集合有各自数据结构特点,总结如下:
数组结构:一块连续的存储区域
链表结构:每个元素指向下一个元素
队列结构:容器先进先出的规则
栈结构:容器先进后出规则
集合嵌套并不是一个新的知识点,仅仅是集合内容又是集合,如单列集合嵌套、双列集合与单列集合嵌套、双列集合嵌套。
单列集合嵌套:
大学(List表示)有多个分校(list表示),每个分校有多个班级(字符串)。
双列集合与单列集合嵌套
大学(Map表示,key:分校名称、value:分校集合)
有多个分校(List表示)
每个分校有多个班级(字符串)。
双列集合嵌套
大学(Map表示,key:分校名称、value:分校集合)
有多个分校(Map表示,key:班级名称、value 班级对象)
每个分校有多个班级(自定义班级类MyClass)。
如Collection集合嵌套、Collection集合与Map集合相互嵌套、Map集合嵌套。
ArrayList< ArrayList<String> >
Collection< ArrayList<Integer> >
HashMap<String, ArrayList<Person>>
ArrayList< HashMap<String, String>>
HashMap<String, HashMap<String,String>>
HashMap<String, HashMap<Person,String>>
按照斗地主的规则,完成洗牌发牌的动作。
具体规则:
1. 组装54张扑克牌
2. 将54张牌顺序打乱
3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。
4. 查看三人各自手中的牌(按照牌的大小排序)、底牌
完成数字与纸牌的映射关系:
使用双列Map(HashMap)集合,完成一个数字与字符串纸牌的对应关系(相当于一个字典)。
通过数字完成洗牌发牌
将每个人以及底牌设计为ArrayList<String>,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌。
存放的过程中要求数字大小与斗地主规则的大小对应。
将代表不同纸牌的数字分配给不同的玩家与底牌。
通过Map集合找到对应字符展示。
通过查询纸牌与数字的对应关系,由数字转成纸牌字符串再进行展示
首先,要修改java文件编码,由GBK修改为UTF-8,因为默认的字符编码GBK没有我们要的梅花、方片、黑桃、红桃(♠♥♦♣)等特殊字符。
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
/*
* 斗地主洗牌发牌排序
*/
public class Poker {
public static void main(String[] args) {
//准备花色
ArrayList<String> color = new ArrayList<String>();
color.add("♠");
color.add("♥");
color.add("♦");
color.add("♣");
//准备数字
ArrayList<String> number = new ArrayList<String>();
Collections.addAll(number,"3","4","5","6","7","8","9","10","J","Q","K","A","2");
//定义一个map集合:用来将数字与每一张牌进行对应
HashMap<Integer, String> map = new HashMap<Integer, String>();
int index = 0;
//加入大小王
map.put(index++, "小☺");
map.put(index++, "大☻");
for (String thisNumber : number) {
for (String thisColor : color) {
map.put(index++, thisColor+thisNumber);
}
}
//一副54张的牌 ArrayList里边为0-53的数的新牌
ArrayList<Integer> cards = new ArrayList<Integer>();
for (int i = 0; i <= 53; i++) {
cards.add(i);
}
//洗牌
Collections.shuffle(cards);
//创建三个玩家和底牌
ArrayList<Integer> iPlayer = new ArrayList<Integer>();
ArrayList<Integer> iPlayer2 = new ArrayList<Integer>();
ArrayList<Integer> iPlayer3 = new ArrayList<Integer>();
ArrayList<Integer> itCards = new ArrayList<Integer>();
//遍历这副洗好的牌,遍历过程中,将牌发到三个玩家和底牌中
for (int i = 0; i < cards.size(); i++) {
if(i>=51) {
iCards.add(cards.get(i));
} else {
if(i%3==0) {
iPlayer.add(cards.get(i));
}else if(i%3==1) {
iPlayer2.add(cards.get(i));
}else {
iPlayer3.add(cards.get(i));
}
}
}
//对每个人手中的牌排序
Collections.sort(iPlayer);
Collections.sort(iPlayer2);
Collections.sort(iPlayer3);
//对应数字形式的每个人手中的牌,定义字符串形式的牌
ArrayList<String> sPlayer = new ArrayList<String>();
ArrayList<String> sPlayer2 = new ArrayList<String>();
ArrayList<String> sPlayer3 = new ArrayList<String>();
ArrayList<String> sCards = new ArrayList<String>();
for (Integer key : iPlayer) {
sPlayer.add(map.get(key));
}
for (Integer key : iPlayer2) {
sPlayer2.add(map.get(key));
}
for (Integer key : iPlayer3) {
sPlayer3.add(map.get(key));
}
for (Integer key : iCards) {
sCards.add(map.get(key));
}
//看牌
System.out.println(sPlayer);
System.out.println(sPlayer2);
System.out.println(sPlayer3);
System.out.println(sCards);
}
}
题目:
1) 定义类,定义main()方法,按以下要求编写代码:
数组结构:一块连续的存储区域
链表结构:每个元素指向下一个元素
队列结构:容器先进先出的规则
栈结构:容器先进后出规则
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
/*
* String s = "aliajflajfajfkjlajoiwpreiepoeroiewhroagflmslkgnmlkcnksahfoaphgnkjfia";
*
* 请你统计出,每个字母出现的次数.
* a - 2
* l - 1
* i - 1
* j - 1
*
* 1.遍历字符串
* 2.保存到map 中 , 字母作为键 Character ,次数作为值 Integer
* 3.map ,即是结果, 遍历 map .
*
*/
public class Test {
public static void main(String[] args) {
String s = "aliajflajfajfkjlajoiwpreiepoeroiewhroagflmslkgnmlkcnksahfoaphgnkjfia";
//创建map
HashMap<Character,Integer> hashMap = new HashMap<>();
// 1.遍历字符串
for (int i = 0; i < s.length() ; i++) {
char key = s.charAt(i); // ch 为每一个字母.
//2.保存到map 中 , 字母作为键 Character ,次数作为值 Integer
//判断 是否包含key , 再保存.
if (hashMap.containsKey(key)) {
// 包含,存过
//Integer count = hashMap.get(key);// 获取之前次数,
//count++; // + 1
hashMap.put(key, hashMap.get(key) + 1); // 再 保存
}else {
// 不包含 , 第一次存.
hashMap.put(key, 1);
}
}
// 3. 遍历map
Set<Entry<Character,Integer>> entrySet = hashMap.entrySet();
System.out.println( "字母 -- 次数 " );
for (Entry<Character, Integer> entry : entrySet) {
System.out.println(entry.getKey() +" -- "+ entry.getValue());
}
}
}
package day09_Test基础练习题;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test001 {
//创建一个Map集合,添加数据进行测试,使用Map集合的两种遍历方式进行遍历
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("李连杰", "男人");
map.put("林志玲", "女人");
map.put("泰国有", "人妖");
//map集合第一种遍历方式
/*Set<Entry<String, String>> set = map.entrySet();
for (Entry<String, String> entry : set) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("key="+key+",value="+value);
}*/
//map集合第二种遍历方式
Set<String> set = map.keySet();
for (String key : set) {
String value = map.get(key);
System.out.println("key="+key+",value="+value);
}
}
}
定义一个测试类,在测试类中定义main()方法,按以下要求编写代码
1.实例化一个Map<String,String>集合
2.向集合内添加以下内容:
"NO01","安森"
"NO01","凯特"
"NO02","安森"
3.遍历集合,观察打印结果,请说明
4.如果存储“相同的键”时,会发生什么情况
5.如果存储“不同的键”,“相同的值”时,会怎样?
package day09_Test基础练习题;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Test002 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("NO01", "安森");
map.put("NO02", "凯特");
map.put("NO03", "安森");
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("key="+key+",value="+value);
}
System.out.println("---------------存储相同的键-------------------------");
map.put("NO01", "李安");
//查看map
System.out.println(map);//将原先的值给覆盖了
System.out.println("---------------存储不同的键---------------------");
map.put("NO09", "008");
//查看此时的map
System.out.println(map);//存储到Map中了
}
}
定义Student类,要求有如下成员:
成员属性(私有):
姓名(String类型)
性别(String类型)
年龄(int 类型)
构造方法:
无参
全参
成员方法:
get/set方法
(有兴趣,可以将toString()方法也添加上)
定义类测试类,在测试类中定义main()方法,按以下要求编写代码:
“it001”,new Student(“王宝强”,’男’,20);
“it002”,new Student(“马蓉”,’女’,18);
“it003”,new Student(“宋喆”,’男’,19);
Student类:
package day09_Test基础练习题;
public class Student {
private String name;
private char sex;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, char sex, int age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
}
测试类:
package day09_Test基础练习题;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Test003 {
public static void main(String[] args) {
Map<String, Student> map = new HashMap<>();
map.put("it001", new Student("王宝强", '男', 20));
map.put("it002", new Student("马蓉", '女', 18));
map.put("it003", new Student("宋哲", '男', 19));
//第一种方式
/*Set<String> keSet = map.keySet();
for (String key : keSet) {
Student student = map.get(key);
System.out.println("key="+key+",student的信息如下:"+student);
}*/
//第二种方式
Set<Entry<String, Student>> entrySet = map.entrySet();
for (Entry<String, Student> entry : entrySet) {
String key = entry.getKey();
Student student = entry.getValue();
System.out.println("key="+key+",student的信息如下:"+student);
}
}
}
定义类Cat类,要求有以下成员:
成员属性(私有):
姓名
性别
年龄
构造方法:
无参
全参
成员方法:
get/set方法
定义一个测试类,在测试类中定义main()方法:
l在main()中按以下要求编写代码:
new Cat(“波斯猫”,’公’,2),”No01”
new Cat(“折耳猫”,’母’,1),”No02”
new Cat(“折耳猫”,’母’,1),”No03”
package day09_Test基础练习题;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Test004 {
public static void main(String[] args) {
Map<Cat, String> map = new HashMap<>();
map.put(new Cat("波斯猫", '公', 2), "No01");
map.put(new Cat("折耳猫", '母', 1), "No02");
map.put(new Cat("折耳猫", '母', 1), "No03");
//遍历
Set<Entry<Cat, String>> entrySet = map.entrySet();
for (Entry<Cat, String> entry : entrySet) {
Cat cat = entry.getKey();
String value = entry.getValue();
System.out.println("Cat="+cat+",value="+value);
}
}
}
package day09_Test基础练习题;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
public class Test005 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(11);
list.add(222);
list.add(3);
list.add(40);
list.add(5);
//Collections.sort(list);
System.out.println("此时的list集合元素为:"+list);
//HashSet
HashSet<Integer> set = new HashSet<>();
set.add(23);
set.add(2);
set.add(203);
set.add(24);
set.add(3);
System.out.println("没有排序的set="+set);
//Collections.sort(set);使用Collections集合的sort方法里面只能放入List集合,不能放入set集合
//打印ArrayList集合
Collections.shuffle(list);
System.out.println("打乱顺序的list集合元素为:"+list);
}
定义一个Map,存储如下内容:
老师 课程
Tom CoreJava
John Oracle
Susan Oracle
Jerry JDBC
Jim Unix
Kevin JSP
Lucy JSP
完成以下要求:
1).增加一位新老师Allen教JDBC;
2).Lucy改为教CoreJava
3).使用两种方式遍历集合;
4).输出所有教JDBC的讲师
package day09_Test拓展三道编程题;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test001 {
/*.定义一个Map,存储如下内容:
老师 课程
Tom CoreJava
John Oracle
Susan Oracle
Jerry JDBC
Jim Unix
Kevin JSP
Lucy JSP
完成以下要求:
1).增加一位新老师Allen教JDBC;
2).Lucy改为教CoreJava
3).使用两种方式遍历集合;
4).输出所有教JDBC的讲师;*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("Tom", "CoreJava");
map.put("John", "Oracle");
map.put("Susan", "Oracle");
map.put("Jerry", "JDBC");
map.put("Jim", "Unix");
map.put("Kevin", "JSP");
map.put("Lucy", "JSP");
//1).增加一位新老师Allen教JDBC;
map.put("Allen", "JDBC");
//2).Lucy改为教CoreJava
map.put("Lucy", "CoreJava");
//3).使用两种方式遍历集合;
//--方式一:获取所有键的集合
Set<String> keys = map.keySet();
for(String k : keys){
System.out.println(k + "," + map.get(k));
}
//--方式二:获取所有键值对的集合
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for(Map.Entry<String, String> e : entrySet){
System.out.println(e.getKey() + "," + e.getValue());
}
//4).输出所有教JDBC的讲师;
for(String k : keys){
if(map.get(k).equals("JDBC")){
System.out.println("讲师:" + k + " 教JDBC");
}
}
}
}
1.定义一个类Demo;
2.内部定义一个静态方法asList,此方法可以接收任意多的String类型参数,方法功能:将所有String参数的值存储到一个具有String泛型的List集合中,并将此集合返回;
3.在Demo类中定义main()方法,并调用asList方法获取返回值,并遍历集合
package day09_Test拓展三道编程题;
import java.util.ArrayList;
import java.util.List;
public class Test002 {
/*
* 1.定义一个类Demo;
2.内部定义一个静态方法asList,此方法可以接收任意多的String类型参数,
方法功能:将所有String参数的值存储到一个具有String泛型的List集合
中,并将此集合返回;
3.在Demo类中定义main()方法,并调用asList方法获取返回值,并遍历集
合;
*/
public static void main(String[] args) {
List<String> strList = asList("Java","Oracle","MySql","JDBC","JSP","HTML","jQuery");
for(String s : strList){
System.out.println(s);
}
}
private static List<String> asList(String ... values) {
List<String> strList = new ArrayList<>();
for(String s : values){
strList.add(s);
}
return strList;
}
}
成龙,甄子丹,李连杰三个人打斗地主,三人约定,洗牌后,随机抽取一张"明牌"并夹在中间;然后依次抓牌,谁抓到这张便自动作为地主,并收取最后三张。
要求:请用程序实现这一过程,最后打印地主名,以及三个人的牌(要求排序);
思路:
1.定义一个Map集合存储一副扑克牌;List存储编号;
2.洗牌;
3.随机抽取一个索引(该值必须在倒数三张之前),用于表示"明牌",在发牌时谁抓到这一张便作为"地主";
4.依次给三个人(成龙,甄子丹,李连杰)发牌,并监督谁作为地主;地主自动收取最后三张。
5.打印地主名;
6.最后以排序后的方式打印每个人手里的牌
package day09_Test拓展三道编程题;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class Test003 {
/*成龙,甄子丹,李连杰三个人打斗地主,三人约定,洗牌后,随机抽取一张"明牌"并夹在中间;然后依次抓牌,谁抓到这张便自动作为地主,并收取最后三张。
要求:请用程序实现这一过程,最后打印地主名,以及三个人的牌(要求排序);
思路:
1.定义一个Map集合存储一副扑克牌;List存储编号;
2.洗牌;
3.随机抽取一个索引(该值必须在倒数三张之前),用于表示"明牌",在发牌
时谁抓到这一张便作为"地主";
4.依次给三个人(成龙,甄子丹,李连杰)发牌,并监督谁作为地主;地主自
动收取最后三张。
5.打印地主名;
6.最后以排序后的方式打印每个人手里的牌
*/
public static void main(String[] args) {
String[] colors = {"♥","♦","♠","♣"};
String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
Map<Integer,String> pokerMap = new HashMap<>();
List<Integer> indexList = new ArrayList<>();
int index = 1;
for(String n : numbers){
for(String c : colors){
pokerMap.put(index, c + n);
indexList.add(index);
index++;
}
}
pokerMap.put(index, "小王");
indexList.add(index);
index++;
pokerMap.put(index, "大王");
indexList.add(index);
//2.洗牌
Collections.shuffle(indexList);
//3.随机抽取一张作为明牌
int flagIndex = -1;
Random rdm = new Random();
flagIndex = rdm.nextInt(indexList.size() - 3);
System.out.println("明牌索引:" + flagIndex);
//4.发牌
List<Integer> chenglongList = new ArrayList<>();
List<Integer> zhenzidanList = new ArrayList<>();
List<Integer> lilianjieList = new ArrayList<>();
int dizhu = 0;//1.成龙;2.甄子丹;3.李连杰
for(int i = 0;i < indexList.size() ; i++){
if(i >= indexList.size() - 3){
if(dizhu == 1){
chenglongList.add(indexList.get(i));
}else if(dizhu == 2){
zhenzidanList.add(indexList.get(i));
}else if(dizhu == 3){
lilianjieList.add(indexList.get(i));
}
}else{
if(i % 3 == 0){
chenglongList.add(indexList.get(i));
if(i == flagIndex){
dizhu = 1;
System.out.println("地主:成龙");
}
}else if(i % 3 == 1){
zhenzidanList.add(indexList.get(i));
if(i == flagIndex){
dizhu = 2;
System.out.println("地主:甄子丹");
}
}else if(i % 3 == 2){
lilianjieList.add(indexList.get(i));
if(i == flagIndex){
dizhu = 3;
System.out.println("地主:李连杰");
}
}
}
}
//排序
Collections.sort(chenglongList);
Collections.sort(zhenzidanList);
Collections.sort(lilianjieList);
//看牌
System.out.println("成龙:" + lookPoker(chenglongList,pokerMap));
System.out.println("甄子丹:" + lookPoker(zhenzidanList,pokerMap));
System.out.println("李连杰:" + lookPoker(lilianjieList,pokerMap));
}
public static String lookPoker(List<Integer> list,Map<Integer,String> pokerMap){
StringBuffer buf = new StringBuffer("[");
for(int i = 0;i < list.size() ; i++){
buf.append(pokerMap.get(list.get(i)));
if(i < list.size() - 1){
buf.append(", ");
}
}
buf.append("]");
return buf.toString();
}
}