集合框架2
05-Set接口与实现类的使用
1.Set及其实现类特点
java.util.Collection:存储一个一个的数据
l-----子接口:Set:存储无序的、不可重复的数据(高中学习的集合)
l---- HashSet:主要实现类:主要实现类;底层使用的是HashMap,即使用数组+单向链表+红黑树结构进行存储。(jdk8中)
l---- LinkedHashSet: 是HashSet的子类;在现有的数组+单向链表+红黑树结构的基础上,又添加了一组双向链表,用于记录添加元素的先后顺序。即:我们可以按照添加元素的顺序实现遍历。便于频繁的查询操作。
l---- TreeSet: 底层使用红黑树存储。可以按照添加的元素的指定的属性的大小顺序进行遍历。
2.开发中的使用频率及场景:
- 较List、Map来说,Set使用的频率比较少。
- 用来过滤重复数据
4.Set中无序性、不可重复性的理解(以HashSet及其子类为例说明)
- 无序性:
- !=随机性。
- 添加元素的顺序和遍历元素的顺序不一致,是不是就是无序性呢?No !
- 到底什么是无序性?与添加的元素的位置有关,不像ArrayList一样是依次紧密排列的。
- 这里是根据添加的元素的哈希值,计算的其在数组中的存储位置。此位置不是依次排列的,表现为无序性。
- 不可重复性:添加到Set中的元素是不能相同的。
- 比较的标准,需要判断hashCode()得到的哈希值以及equals()得到的boolean型的结果
- 哈希值相同且equals()返回true,则认为元素是相同的。
5.添加到HashSet/LinkedHashSet中元素的要求:
要求元素所在的类要重写两个方法: equals() 和hashCode()。
同时,要求equals()和 hashCode()要保持一致性!我们只需要在IDEA中自动生成两个方法的重写即可,
public void test1(){
HashSet set = new HashSet();
set.add("aa");
set.add(123);
set.add("sef");
set.add(new Person("ad",9));
set.add(new Student("aa",4));
set.add(new Student("aa",4));
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
6.TreeSet的使用
6.1 底层的数据结构:红黑树
6.2添加数据后的特点:可以按照添加的元素的指定的属性的大小顺序进行遍历。
6.3向TreeSet中添加的元素的要求:
- 要求添加到TreeSet中的元素必须是同一个类型的对象,否则会报ClassCastException.
- 添加的元素需要考虑排序:1自然排序②定制排序
6.4判断数据是否相同的标准
- 不再是考虑hashCode()和equals()方法了,也就意味着添加到TreeSet中的元素所在的类不需要重写hashCode()和equals()方法
- 比较元素大小的或比较元素是否相等的标准就是考虑自然排序或定制排序中,compareTo()或compare()的返回值。如果compareTo()或compare()的返回值为0,则认为两个对象是相等的。由于TreeSet中不能存放相同的元素,则后一个相等的元素就不能添加到TreeSet中。
public void test3(){
Comparator comparator = new Comparator() {
/**
* 按照姓名从小到大排列,如果姓名相同,继续比较age,按照从大到小排列
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return
*/
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Student && o2 instanceof Student){
Student s1=(Student) o1;
Student s2=(Student) o2;
int value=s1.getName().compareTo(s2.getName());
if (value!=0){
return value;
}
return s2.getAge()-s1.getAge();
}
throw new RuntimeException("类型不匹配");
}
};
TreeSet set = new TreeSet(comparator);
Student x1 = new Student("aa", 54);
Student x2 = new Student("bb", 11);
Student x3 = new Student("cc", 25);
Student x4 = new Student("dd", 54);
set.add(x1);
set.add(x2);
set.add(x3);
set.add(x4);
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
06-Map接口及实现类的使用
1.Map及其实现类对比
java.util.Map:存储一对一对的数据(key-value键值对,(x1, y1)、(x2,y2) --> y=f(x),类似于高中的函数)
- HashMap :主要实现类;线程不安全的,效率高;可以添加null的key和value值;底层使用数组+单向链表+红黑树结构存储(jdk8)
- LinkedHashMap:是HashMap的子类:在HashMap使用的数据结构的基础上,增加了一对双向链表,用于记录添加的元素的先后顺序,
进而我们在遍历元素时,就可以按照添加的顺序显示。
开发中,对于频繁的遍历操作,建议使用此类。
- LinkedHashMap:是HashMap的子类:在HashMap使用的数据结构的基础上,增加了一对双向链表,用于记录添加的元素的先后顺序,
- TreeMap:底层使用红黑树存储;可以按照添加的key-value中的key元素的指定的属性的大小顺序进行遍历。需要考虑使用①自然排序②定制排序。
- Hashtable :古老实现类;线程安全的,效率低;不可以添加null的key或value值;底层使用数组+单向链表结构存储(jdk8)
- Properties:其key和value都是String类型。常用来处理属性文件。
2.HashMap中元素的特点
- HashMap中的所有的key彼此之间是不可重复的、无序的。所有的key就构成一个Set集合。
- key所在的类要重写hashCode()和equals()
- HashMap中的所有的value彼此之间是可重复的、无序的。所有的value就构成一个Collection集合。
- value所在的类要重写equals()
- HashMap中的一个key-value,就构成了一个entry。
- HashMap中的所有的entry彼此之间是不可重复的、无序的。所有的entry就构成了一个Set集合
6.2 Map接口的常用方法
- 添加、修改操作:
- object put(Object key,object value):将指定key-value添加到(或修改)当前map对象中
- void putAll(Map m):将m中的所有key-value对存放到当前map中
- 删除操作:
- object remove(Object key):移除指定key的key-value对,并返回value
- void clear():清空当前map中的所有数据
- 元素查询的操作:
- object get(Object key):获取指定key对应的value
- boolean containsKey(Object key):是否包含指定的key
- boolean containsvalue(object value):是否包含指定的value
- int size():返回map中key-value对的个数
- boolean isEmpty():判断当前map是否为空
- boolean equals(object obj):判断当前map和参数对象obj是否相等
小结:
-
增:
put(Object key ,0bject value)putAll(Map m) -
删:
0bject remove(0bject key) -
改;
put(Object key ,0bject value)putAll(Map m) -
查:
0bject get(object key) -
长度:
size() -
遍历:
- 遍历key集: Set keySet(
- 遍历value集:Collection values()
- 遍历entry集:Set entrySet()
public void test4(){
// 增:
// put(Object key ,0bject value)putAll(Map m)
HashMap map = new HashMap();
map.put("aa",44);
map.put("ee",44);
map.put(11,498);
map.put(15,"aa");
System.out.println(map);
System.out.println(map.size());
//remove
Object e = map.remove("ee");
System.out.println(e);//44
System.out.println(map);//{aa=44, 11=498, 15=aa}
//修改
Object eldValue = map.put("aa", 99);
System.out.println(eldValue);//44
System.out.println(map);//{aa=99, 11=498, 15=aa}
//
Object value1 = map.get(11);
System.out.println(value1);
}
public void test5(){
HashMap map = new HashMap();
map.put("aa",44);
map.put("ee",44);
map.put(11,498);
map.put(15,"aa");
System.out.println(map);
/*
遍历:
- 遍历key集: Set keySet(
- 遍历value集:Collection values()
- 遍历entry集:Set entrySet()
*/
//方式1
Set keySet = map.keySet();
//使用迭代器
Iterator iterator = keySet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("========");
//方式2
Collection values = map.values();
for (Object o :
values) {
System.out.println(o);
}
System.out.println("========");
//方式3
for (Object key : map.keySet()) {
Object o = map.get(key);
System.out.println(o);
}
}
遍历entry集:Set entrySet()
public void test6(){
HashMap map = new HashMap();
map.put("aa",44);
map.put("ee",44);
map.put(11,498);
map.put(15,"aa");
//
/*Set set = map.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()){
//方式1
Map.Entry entry= (Map.Entry) iterator.next();
System.out.println(entry.getKey()+"--->"+entry.getValue());
//方式2
System.out.println(iterator.next());
}*/
//方式3
Set key1 = map.keySet();
for (Object k : key1) {
System.out.println(k+"--->"+map.get(k));
}
}
4.TreeMap的使用
- 底层使用红黑树存储;
- 可以按照添加的key-value中的key元素的指定的属性的大小顺序进行遍历。
- 需要考虑使用①自然排序②定制排序。
- 要求:向TreeMap中添加的key必须是同一个类型的对象。
//自然排序
public void test1(){
TreeMap treeMap = new TreeMap();
treeMap.put("ss",45);
treeMap.put("tt",23);
treeMap.put("ee",66);
treeMap.put("ww",45);
//map.put(67,78);//报错。因为key的类型(Integer)与之前的key的类型(String)不一致
for (Object o : treeMap.entrySet()) {
System.out.println(o);
}
}
public void test2(){
TreeMap m = new TreeMap();
Student x1 = new Student("aa", 54);
Student x2 = new Student("bb", 11);
Student x3 = new Student("cc", 25);
Student x4 = new Student("dd", 54);
m.put(x1,78);
m.put(x2,23);
m.put(x3,55);
m.put(x4,67);
for (Object o : m.entrySet()) {
System.out.println(o);
}
}
//定制排序
public void test3(){
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Student && o2 instanceof Student){
Student s1=(Student) o1;
Student s2=(Student) o2;
int bi = s1.getName().compareTo(s2.getName());
if (bi!=0){
return bi;
}else {
return s1.getAge()-s2.getAge();
}
}
throw new RuntimeException("类型不一致");
}
};
TreeMap map = new TreeMap(comparator);
Student x1 = new Student("aa", 54);
Student x2 = new Student("bb", 11);
Student x3 = new Student("cc", 25);
Student x4 = new Student("dd", 54);
map.put(x1,78);
map.put(x2,23);
map.put(x3,55);
map.put(x4,67);
for (Object o : map.entrySet()) {
System.out.println(o);
}
}
-
Hashtable与Properties的使用
Properties:是Hashtable的子类,其key和value都是String类型的,常用来处理属性文件。
//注意:因为设计到流的操作,为了确保流能关闭,建议使用try-catch-finally
//方式1:数据和代码耦合度高;如果修改的话,需要重写的编译代码、打包发布,繁琐数据
String name = "Tom ";
String password = "abc123";
//代码:用于操作name , password
// ...
//方式2:将数据封装到具体的配置文件中,在程序中读取配置文件中的信息。实现了数据和代码的解耦;由于我们没有修改代码,就省去了重新编译和打包的过程。
File file = new File( pathname: "info.properties");
//注意,要提前创建好
system.out.println(file.getAbsolutePath());
FileInputStream fis = new FileInputStream(file);
Properties pros = new Properties();
pros.load(fis);//加载流中的文件中的数据
//读取数据
string name = pros.getProperty( "name " );
String pwd = pros.getProperty( "password" );
system.out.println(name + ":" + pwd);
}
案例:二级联动
将省份和城市的名称保存在集合中,当用户选择省份以后,二级联动,显示对应省份的地级市供用户选择。
package com.xin.kuangjia.demo02;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Day90301 {
public static void main(String[] args) {
//1. 获取Map,并遍历map中的所有的key
Map map = CityMap.model;
Set provinces = map.keySet();
for (Object province : provinces) {
System.out.print(province+"\t\t");
}
//2.根据提示,从键盘获取省份值,判断此省份是否存在,如果存在遍历其value中的各个城市。
// 如果不存在,提示用户重新输入
Scanner scanner = new Scanner(System.in);
String[] cities;
while (true){
System.out.println("\n请选择你所在的省份:");
String province = scanner.next();
//获取省份对应的各个城市构成的String[]
cities= (String[]) map.get(province);
if (cities==null||cities.length==0){
System.out.println("你输入的省份有误,请重新输入");
}else break;//意味着用户输入的省份是存在的,则跳出当前循环
}
for (String city : cities) {
System.out.print(city+"\t\t");
}
//3.根据提示,从键盘获取城市,遍历各个城市构成的String[],判断输入的城市是否存在于此数组中
// 如果存在,信息登记完毕。如果不存在,提示用户重新输入。
l:while (true){
System.out.println("请选择你所在的城市");
String city = scanner.next();
for (String c : cities) {
if (c.equals(city)){
System.out.println("信息登记完毕");
break l;
}
}
System.out.println("用户不存在,重新输入");
}
scanner.close();
}
}
class CityMap {
public static Map model = new HashMap();
static {
model.put("北京", new String[]{"北京"});
model.put("辽宁", new String[]{"沈阳", "盘锦", "铁岭", "丹东", "大连", "锦州", "营口"});
model.put("吉林", new String[]{"长春", "延边", "吉林", "白山", "白城", "四平", "松原"});
model.put("河北", new String[]{"承德", "沧州", "邯郸", "邢台", "唐山", "保定", "石家庄"});
model.put("河南", new String[]{"郑州", "许昌", "开封", "洛阳", "商丘", "南阳", "新乡"});
model.put("山东", new String[]{"济南", "青岛", "日照", "临沂", "泰安", "聊城", "德州"});
}
}
7.Collections工具类
参考操作数组的工具类: Arrays,Collections是一个操作 set、List和Map等集合的工具类.
7.1常用方法
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法(均为static方法)∶
排序操作:
- reverse(List):反转 List中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定List集合元素按升序排序
- sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
- swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
查找、替换操作
- static int binarySearch(List> list, T key) 使用二分搜索法搜索指定列表,以获得指定对象在List集合中的索引。 注意:此前必须保证List集合中的元素已经处于有序状态。
- static Object max(Collection coll) 根据元素的自然顺序,返回给定collection 的最大元素。
- static Object max(Collection coll,Comparator comp): 根据指定比较器产生的顺序,返回给定 collection 的最大元素。
- static Object min(Collection coll): 根据元素的自然顺序,返回给定collection 的最小元素。
- static Object min(Collection coll,Comparator comp):根据指定比较器产生的顺序,返回给定 collection 的最小元素。
- static void fill(List list, T obj) : 使用指定元素替换指定列表中的所有元素。
- static int frequency(Collection c, Object o) 返回指定 collection 中等于指定对象的出现次数。
- static int indexOfSubList(List source, List target) : 返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。
- static int lastIndexOfSubList(List source, List target) 返回指定源列表中最后一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。
- static boolean replaceAll(List list, T oldVal, T newVal) 使用一个新值替换List对象的所有旧值oldVal
- void copy(List dest,List src):将src中的内容复制到dest中
public void test1(){
List<Integer> list = Arrays.asList(45, 85, 4, 6, 48, 48, 344, 64, 44, 3, 9);
List<Object> list1 = Arrays.asList(new Object[list.size()]);
Collections.copy(list1,list);
System.out.println(list1);
}
-
提供了多个unmodifiableXxx()方法,该方法返回指定Xxx的不可修改的视图。
public void test2(){ ArrayList list = new ArrayList(); //list可以写入数据 list.add(25); list.add(85); list.add(56); List list1 = Collections.unmodifiableList(list); ///此时的list1只能读,不能写 // list1.add(55);UnsupportedOperationException System.out.println( list1.get(1)); }
-
Collections类中提供了多个synchronizedXxx()方法
//Collections类中提供了多个synchronizedXxx()方法
List list1 = new ArrayList();
//返回的list2就是线程安全的
List list2 = Collections.synchronizedList(list1);
3.面试题:区分Collection和 Collections
- collection:集合框架中的用于存储一个一个元素的接口,又分为List和Set等子接口。
- collections:用于操作集合框架的一个工具类。此时的集合框架包括: Set、List、Map
模拟斗地主洗牌和发牌,牌没有排序
package com.xin.kuangjia.demo03;
import java.util.ArrayList;
import java.util.Collections;
public class Day90300 {
public static void main(String[] args) {
//1.组成一副扑克牌
String[] num = {"A", "2","3","4","5","6","7" , "8", "9","10","J","Q","K"};
String[] color = {"方片◆", "梅花","红桃","黑桃●"};
ArrayList poker = new ArrayList();
for (int i = 0; i < color.length; i++) {
for (int j = 0; j < num.length; j++) {
poker.add(color[i]+"\t"+num[j]);
}
}
//添加大小王
poker.add("大王");
poker.add("小王");
//2.洗牌
Collections.shuffle(poker);
//3.发牌
//3.1 创建3个角色和1个底牌对应的4个ArrayList
ArrayList tom = new ArrayList();
ArrayList jerry = new ArrayList();
ArrayList me = new ArrayList();
ArrayList lastcard = new ArrayList();
for (int i = 0; i < poker.size(); i++) {
if (i>=poker.size()-3){
lastcard.add(poker.get(i));
} else if (i % 3 == 0) {
tom.add(poker.get(i));
}else if (i % 3 == 1) {
jerry.add(poker.get(i));
}else if (i % 3 == 2) {
me.add(poker.get(i));
}
}
//3.2遍历显示4个ArrayList
System.out.println("tom");
System.out.println(tom);
System.out.println("jerry");
System.out.println(jerry);
System.out.println("me");
System.out.println(me);
System.out.println("lastcard");
System.out.println(lastcard);
}
}
标签:map,框架,System,println,key,集合,new,out From: https://www.cnblogs.com/xin-zhi-suo-xiang/p/17675361.html