欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > Java入门-Map双列集合

Java入门-Map双列集合

2025/4/19 12:47:38 来源:https://blog.csdn.net/qq_52241267/article/details/147150534  浏览:    关键词:Java入门-Map双列集合

(一)可变参数

案例:假如需要定义一个方法求和,该方法可以灵活的完成如下需求:

l 计算 1 个数据的和
l 计算 2 个数据的和。
l 计算 3 个数据的和。
l 计算 n 个数据的和,甚至可以支持不接收参数进行调用。

package MyCollections;import java.util.Arrays;/*认识可变参数,掌握作用*/
public class ParamTest {public static void main(String[] args) {//test();//不传数据test(10);test(10,20,30);//传多个数据test(new int[]{10,20,30,40});//传一个数组给可变参数}public static void test(int...nums){//可变参数在方法内部时本质是一个数组System.out.println(nums.length);System.out.println(Arrays.toString(nums));System.out.println("------------------");}
}

注意:

(1)一个形参列表中,只能有一个可变参数

(2)可变参数必须放在形参列表的最后面 

(3)可变参数在方法内部就是一个数组

(二)工具类Collections

Collections:是一个用来操作集合的工具类

Collections提供的常用静态方法:

方法名称

说明

public static <T> boolean addAll(Collection<? super T> c, T... elements)

给集合批量添加元素

public static void shuffle(List<?> list)

打乱List集合中的元素顺序

public static <T> void sort(List<T> list)

List集合中元素进行升序排序

public static <T> void sort(List<T> list,Comparator<? super T> c)

List集合中元素按照比较器对象

指定的规则进行排序

public static <T> boolean addAll(Collection<? super T> c, T... elements) 分析:

(1)public static:这表明该方法是公共的静态方法,可直接通过 Collections 类调用,无需创建 Collections 类的实例

(2)该方法的返回类型为 boolean,表示操作是否成功

(3)Collection<? super T> c:此为方法的第一个参数,是一个 Collection 类型的集合。? super T 是泛型通配符,代表该集合可以是 T 类型或者 T 的某个父类型的集合。这就保证了集合能够容纳 T 类型的元素。

(4)T... elements:这是一个可变参数,意味着可以传入任意数量(包括零个)的 T 类型元素。在方法内部,可变参数会被当作 T 类型的数组来处理

package MyCollections;import java.util.*;public class MyCollectionTest {public static void main(String[] args) {//1.public static <T> boolean addAll(Collection<? super T> c, T... elements) 给集合批量添加元素List<String> lis=new ArrayList<>();//Collectios 是工具类,不是List本身自带的方法,所以需要区分Collections.addAll(lis,"a1","a2","a3","a4");System.out.println(lis);//2.public static void shuffle(List<?> list) 打乱List集合中的元素顺序Collections.shuffle(lis);//3.public static <T> void sort(List<T> list) 对List集合中的元素进行升序排序List<Integer> list2=new ArrayList<>();list2.add(2);list2.add(0);list2.add(7);list2.add(5);Collections.sort(list2);System.out.println(list2);//3.2  对自定义对象进行排序(在对象中重写compareTo 实现指定排序方式)List<Student> listS=new ArrayList<>();Student s1=new Student("李彪",99,12.9);Student s2=new Student("Lisa",123,98.9);Student s3=new Student("Tom",79,32.9);Student s4=new Student("Jerry",66,21.3);listS.add(s1);listS.add(s2);listS.add(s3);listS.add(s4);Collections.sort(listS);System.out.println(listS);  //注意,要重写toString方法才能实现获得对象的具体值,否则输出对象地址//public static <T> void sort(List<T> list,Comparator<? super T> c)  对List集合中元素,按照比较器对象指定的规则进行排序Collections.sort(listS, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// return o1.getHeight()-o2.getHeight();  返回的是 double 类型的值,而 compare 方法要求返回 int 类型return Double.compare(o1.getHeight(),o2.getHeight());}});System.out.println(listS);}
}

(三)综合案例

分析业务需求

总共有54张牌
点数: "3","4","5","6","7","8","9","10","J","Q","K","A","2“
花色: "♠", "♥", "♣", "♦“
大小王: "👲" , "🃏“

斗地主发出51张牌,剩下3张为底牌。

(1)创建一个牌的对象,用于记录一张牌的花色,大小和数字

package Example;public class Pai {String color;String num;int size; //用于区分当前牌的大小public Pai(String color, String num, int size) {this.color = color;this.num = num;this.size = size;}public Pai() {}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public String getNum() {return num;}public void setNum(String num) {this.num = num;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public String toString(){return color+","+num+","+size;}
}

(2)创建一个房间,房间里有初始化创建一副新牌操作和开始游戏后发牌操作

package Example;import java.util.*;public class hintDiZhu {/*总共有54张牌
点数: "3","4","5","6","7","8","9","10","J","Q","K","A","2“
花色: "♠", "♥", "♣", "♦“
大小王: "👲" , "🃏“
斗地主:发出51张牌,剩下3张做为底牌。*/private List<Pai> PaiList=new ArrayList<>();public  hintDiZhu(){//无参构造器//生成一铺牌List<String> nums=new ArrayList<>();Collections.addAll(nums,"3","4","5","6","7","8","9","10","J","Q","K","A","2");//System.out.println(nums);List<String> colors=new ArrayList<>();Collections.addAll(colors,"♠", "♥", "♣", "♦");// System.out.println(colors);int size=1;for (int i = 0; i < nums.size(); i++) {for (int i1 = 0; i1 < colors.size(); i1++) {Pai p=new Pai(colors.get(i1),nums.get(i),size);//System.out.println(p.toString());PaiList.add(p);}size++;}//单独存入大小王Pai p1=new Pai("","🃏",++size);Pai p2=new Pai("","👲",++size);PaiList.add(p1);PaiList.add(p2);System.out.print(PaiList);}public void Start(){////将牌打乱,进行发牌Collections.shuffle(PaiList);System.out.println(PaiList);//创建三个数组,代表三个人List<Pai> a1=new ArrayList<>();List<Pai> b1=new ArrayList<>();List<Pai> c1=new ArrayList<>();//开始发牌,依次发,共51张,剩下3张作为地主牌for (int i = 0; i < PaiList.size(); i++) {if(i%3==0){a1.add(PaiList.get(i));}else if(i%3==1){b1.add(PaiList.get(i));}else if(i%3==2){c1.add(PaiList.get(i));}}//对各自的牌进行排序Collections.sort(a1, new Comparator<Pai>() {@Overridepublic int compare(Pai o1, Pai o2) {return Integer.compare(o1.getSize(),o2.getSize());}});Collections.sort(b1,(o1,o2)->Integer.compare(o1.getSize(),o2.getSize()));Collections.sort(c1,(o1,o2)->Integer.compare(o1.getSize(),o2.getSize()));System.out.println("A的牌:");System.out.println(a1);System.out.println("B的牌:");System.out.println(b1);System.out.println("C的牌:");System.out.println(c1);}
}

(3)主函数,用于调用新的房间,启动游戏

package Example;public class Room {public static void main(String[] args) {hintDiZhu r1=new hintDiZhu();//启动游戏r1.Start();}
}

(四)Map集合

(1)认识Map

(2) Map的使用场景

需要存储一一对应的数据时,可以考虑使用map来存储

package MyMap;import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;/*目标:掌握Map集合的特点*/
public class MapTest {public static void main(String[] args) {//HashMap:无序,不重复,无索引Map<String,Integer> map1=new HashMap<>();map1.put("手表",100);map1.put("电话",1982);map1.put("娃娃",87);map1.put("夏天才手表",1990);map1.put("电话移动段",982);map1.put("小娃娃",97);System.out.println(map1);//{手表=100, 电话移动段=982, 夏天才手表=1990, 电话=1982, 娃娃=87, 小娃娃=97}//2.LinkedHashMap 有序(指插入LinkedHashMap的顺序),不重复,无索引Map<String,Integer> map2=new LinkedHashMap<>(); //多态写法,Map是LinkedHashMap的父类map2.put("手表",100);map2.put("电话",1982);map2.put("娃娃",87);map2.put("夏天才手表",1990);map2.put("电话移动段",982);map2.put("小娃娃",97);System.out.println(map2);//{手表=100, 电话=1982, 娃娃=87, 夏天才手表=1990, 电话移动段=982, 小娃娃=97}//3.TreeMap 可排序,不重复,无索引Map<Integer,String> map3=new TreeMap<>();map3.put(12,"djihsah");map3.put(89,"水表");map3.put(78,"董事会决议");map3.put(56,"najhc");map3.put(27,"不知道");System.out.println(map3); //{12=djihsah, 27=不知道, 56=najhc, 78=董事会决议, 89=水表}}
}

1. Map 集合 是什么?什么时候可以考虑使用 Map 集合
Map 集合是键值对集合
需要存储一一对应的数据时,就可以考虑使用 Map 集合来做
2. Map 集合的实现类有哪些?各自的特点是?
HashMap: 元素按照键是无序,不重复,无索引,值不做要求。
LinkedHashMap: 元素按照键是 有序 ,不重复,无索引,值不做要求。 TreeMap :元素按照建是 排序 ,不重复,无索引的, 值不做要求。

(3)map的常见方法

为什么要先学习Map的常用方法 ?lMap是双列集合的祖宗,它的功能是全部双列集合都可以继承过来使用的

Map的常用方法如下:

方法名称

说明

public V put(K key,V value)

添加元素

public int size()

获取集合的大小

public void clear()

清空集合

public boolean isEmpty()

判断集合是否为空,为空返回true , 反之

public V get(Object key)

根据键获取对应值

public V remove(Object key)

根据键删除整个元素

public  boolean containsKey(Object key)

判断是否包含某个键

public boolean containsValue(Object value)

判断是否包含某个值

public Set<K> keySet()

获取全部键的集合

public Collection<V> values()

获取Map集合的全部值

package MyMap;import java.util.HashMap;
import java.util.Map;public class MapMethod {public static void main(String[] args) {Map<String,Integer> map1=new HashMap<>();map1.put("手表",100);map1.put("电话",1982);map1.put("娃娃",87);map1.put("夏天才手表",1990);map1.put("电话移动段",982);map1.put("小娃娃",97);System.out.println(map1);//public int size()	获取集合的大小System.out.println(map1.size());//public void clear()	清空集合// map1.clear();//public boolean isEmpty()	判断集合是否为空,为空返回true , 反之System.out.println(map1.isEmpty());//public V get(Object key)	根据键获取对应值System.out.println(map1.get("电话"));//public V remove(Object key)	根据键删除整个元素,返回值为被删除的值System.out.println(map1.remove(map1.remove("电话")));//public boolean containsKey(Object key)	判断是否包含某个键System.out.println(map1.containsKey("小娃娃"));//public boolean containsValue(Object value)	判断是否包含某个值System.out.println(map1.containsValue(97));//public Set<K> keySet()	获取全部键的集合System.out.println(map1.keySet());//public Collection<V> values()	获取Map集合的全部值System.out.println(map1.values());}
}

(4)map的遍历方式 

1.通过键找值:先获取Map集合的全部键,再通过遍历键来找值

2.键值对:把”键值对“看为一个整体进行遍历 (使用Map.Entry<String,Integer>将一一对应的键值对作为一个整体(Entry对象))  

Set<map.Entry<String,Integer>>  :

调用map集合提供的entrySet方法,将map集合替换成键值对类型的Set集合

 3.Lambda表达式,JDK1.8之后开始的新技术(代码简单)

package MyMap;import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;public class SearchMethods {public static void main(String[] args) {//HashMap:无序,不重复,无索引Map<String,Integer> map1=new HashMap<>();map1.put("手表",100);map1.put("电话",1982);map1.put("娃娃",87);map1.put("夏天才手表",1990);map1.put("电话移动段",982);map1.put("小娃娃",97);//1.通过键找值:先获取Map集合的全部键,再通过遍历键来找值Set<String> Keys=map1.keySet(); //注意集合没有索引,所以不能使用for,但能使用for增强for (String key : Keys) {System.out.println(key+"------------->"+map1.get(key));// System.out.printf("键:%s ------------值:%d\n",key,map1.get(key));}//2.键值对:把”键值对“看为一个整体进行遍历Set<Map.Entry<String,Integer>> entries=map1.entrySet();for (Map.Entry<String, Integer> entry : entries) {System.out.println(entry);}//3.Lambda表达式,JDK1.8之后开始的新技术(代码简单)System.out.println("--------------Lambda-------------");map1.forEach(new BiConsumer<String, Integer>() {@Overridepublic void accept(String k, Integer v) {System.out.println(k+"---"+v);}});//map1.forEach((k,v)->System.out.println(k+"---"+v));   //简化写法}
}

 Lambda表达式内部实现代码:本质还是使用Entry()实现的

  default void forEach(BiConsumer<? super K, ? super V> action) {Objects.requireNonNull(action);for (Map.Entry<K, V> entry : entrySet()) {K k;V v;try {k = entry.getKey();v = entry.getValue();} catch (IllegalStateException ise) {// this usually means the entry is no longer in the map.throw new ConcurrentModificationException(ise);}action.accept(k, v);}}

 (5)map集合的案例

package MyMap;import java.util.HashMap;
import java.util.Map;
import java.util.Random;public class MapExample {public static void main(String[] args) {Map<String,Integer> num=new HashMap<>();//用一个String数组存储可选择的景点String[] s1={"A","B","C","D"};//创建一个随机对象Random r=new Random();int i=0;while(i<80){i++;int index=r.nextInt(4);//0123String key=s1[index];//System.out.println(key);if(num.containsKey(key)){num.put(key,num.get(key)+1);}else{num.put(key,1);}}System.out.println(num);}
}

(五)HashMap底层原理

 

1HashMap的特点和底层原理?

由键决定:无序、不重复、无索引。 HashMap 底层是哈希表结构的。
基于哈希表。增删改查的性能都较好。

2HashMap如何实现键的唯一性的?

依赖 hashCode 方法和 equals 方法保证 的唯一。
如果 要存储的是自定义对象,需要重写 hashCode equals 方法。

package MyMap;import MySet.Student;import java.util.HashMap;
import java.util.Map;//HashMap 存储对象
public class MyHashMap {public static void main(String[] args) {Map<Student, String> map=new HashMap<>(); //map.put(new MySet.Student("牛魔王",888,99.8),"居住洞");map.put(new MySet.Student("牛魔王",888,99.8),"居住洞");map.put(new MySet.Student("小灰灰",18,50.2),"狼堡");map.put(new MySet.Student("喜羊羊",69,78.9),"羊村");System.out.println(map);//设置HashCode和equals之后,才能将名字重复的对象是为同一个对象进行去重}
}
package MyMap;import java.util.Objects;public class Student implements Comparable<Student>{String name;int age;double height;
//this指当前对象 o 指传入的待比较对象@Overridepublic int compareTo(Student o){return this.age-o.age;  //当age是puBlic 时可以直接使用.获取到值,若是private才需要通过Get,Set方法获取}public Student(String name, int age, double height) {this.name = name;this.age = age;this.height = height;}
//------------------------重写的方法
//
//    @Override
//    public boolean equals(Object o) {
//        if (o == null || getClass() != o.getClass()) return false;
//        Student student = (Student) o;  //将传入的对象强制转换为学生对象,
//        return age == student.age && Double.compare(height, student.height) == 0 && Objects.equals(name, student.name);  //当两个对象的值相同时判定为相等
//    }
//
//    @Override
//    public int hashCode() {
//        return Objects.hash(name, age, height);
//    }
//---------------------------@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", height=" + height +'}';}public Student() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getHeight() {return height;}public void setHeight(double height) {this.height = height;}
}

(2)HashMap的案例

package MyMap;import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class HashMapExample {public static void main(String[] args) {//2.创建HashMap集合对象用于存储StudentHashMap<Student,Integer> s=new HashMap<>();//3.创建学生对象Student s1=new Student("牛魔王",888,99.8);Student s2=new Student("小灰灰",18,50.2);Student s3=new Student("喜羊羊",69,78.9);//4.把学生对象添加到集合中s.put(s1,188);s.put(s2,69);s.put(s3,78);//遍历//1.先获取所有的键,再遍历键获取值Set<Student> keys=s.keySet();for(Student key:keys){System.out.println(key+"--->"+s.get(key));}//2只需要知道值:先获取所有的值s.values(),再遍历输出各个值for(Integer value:s.values()){System.out.println(value);}//3.1.遍历键值对:使用s.entrySet() 将键值对看作一个整体Set<Map.Entry<Student,Integer>> entryset= s.entrySet();for (Map.Entry<Student, Integer> studentIntegerEntry : entryset) {System.out.println(studentIntegerEntry.getKey()+"--->"+studentIntegerEntry.getValue());}//3.2.遍历键值对:使用Lambda表达式s.forEach((k,v)-> System.out.println(k+":"+v));}
}

 

(五)LinkedHashMap底层原理(有序,不重复,无索引)

 

package MyMap;import java.util.LinkedHashMap;
import java.util.Map;public class MyLinkedHashMap {public static void main(String[] args) {Map<Integer,String> map=new LinkedHashMap<>();map.put(2,"B");map.put(5,"E");map.put(4,"D");map.put(3,"C");map.put(1,"A");System.out.println(map); // 有序(指插入的顺序){2=B, 5=E, 4=D, 3=C, 1=A}}
}

(六)TreeMap底层原理(默认按键大小升序排序,不重复,无索引)

package MyMap;import java.util.Map;
import java.util.TreeMap;public class MyTreeMap {public static void main(String[] args) {Map<Integer,String> map=new TreeMap<>();map.put(2,"B");map.put(5,"E");map.put(4,"D");map.put(3,"C");map.put(1,"A");System.out.println(map); //{1=A, 2=B, 3=C, 4=D, 5=E}}
}

(七)Map综合案例

 

package MyMap;import java.util.*;public class MyMapExample {public static void main(String[] args) {
//江苏省 = 南京市,扬州市,苏州市,无锡市,常州市
//湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市
//河北省 = 石家庄市,唐山市,邢台市,保定市,张家口市HashMap<String,List<String>> pro=new HashMap<>();//List<String> citys1=new ArrayList<>();Collections.addAll(citys1, "南京市","扬州市","苏州市","无锡市","常州市");pro.put("江苏省",citys1);List<String> citys2=new ArrayList<>();Collections.addAll(citys2,"武汉市","孝感市","十堰市","宜昌市","鄂州市");pro.put("湖北省",citys2);List<String> citys3=new ArrayList<>();Collections.addAll(citys3,"石家庄市","唐山市","邢台市","保定市","张家口市");pro.put("河北省",citys3);//进行遍历//1 获取所有的键,遍历键获取值Set<String> p=pro.keySet();for (String k : p) {System.out.println(k+":"+pro.get(k));//江苏省:[南京市, 扬州市, 苏州市, 无锡市, 常州市]//湖北省:[武汉市, 孝感市, 十堰市, 宜昌市, 鄂州市]//河北省:[石家庄市, 唐山市, 邢台市, 保定市, 张家口市]}//方法2:使用entrySet()将键值对视为一个整体for(Map.Entry<String,List<String>> entry:pro.entrySet()){System.out.println(entry.getKey()+"--->"+entry.getValue());}//方法3 使用Lambda表达式pro.forEach((k,v)-> System.out.println(k+"--->"+v));}
}

(八)Steam流

List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");

需求:把集合中所有以开头,且是3个字的元素存储到一个新的集合。

package MySteam;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;public class Introduce {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("张无忌");list.add("周芷若");list.add("赵敏");list.add("张强");list.add("张三丰");//需求:把集合中所有以“张”开头,且是3个字的元素存储到一个新的集合。List<String> List2=new ArrayList<>();for (String s : list) {if(s.startsWith("张") && s.length()==3){List2.add(s);}}System.out.println(List2);//使用Steam实现List<String> List3=list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).collect(Collectors.toList());System.out.println(List3);}
}

Ps:

(Add1 :Java的自动装箱和拆箱机制)

注意:Java 的泛型是基于引用类型设计的,泛型类型参数必须是引用类型,不能是基本数据类型。List 作为泛型类,其类型参数也必须是引用类型 。错误代码示范

// 编译错误,泛型类型参数不能是基本数据类型

List<int> intList = new ArrayList<>();

 虽然泛型不支持基本数据类型,但 Java 提供了自动装箱和拆箱机制,让基本数据类型和对应的包装类可以自动转换。Integer 是 int 的包装类,当你把 int 类型的值添加到 List<Integer> 中时,Java 编译器会自动将 int 装箱为 Integer

import java.util.ArrayList;
import java.util.List;public class AutoboxingExample {public static void main(String[] args) {List<Integer> integerList = new ArrayList<>();// 自动装箱:int 类型的值 1 被装箱为 Integer 对象integerList.add(1); int num = integerList.get(0); // 自动拆箱:Integer 对象被拆箱为 int 类型的值System.out.println(num); }
}

整数类型

基本数据类型包装类描述
byteByte8 位有符号整数,取值范围是 -128 到 127。
shortShort16 位有符号整数,取值范围是 -32768 到 32767。
intInteger32 位有符号整数,取值范围是 -2147483648 到 2147483647。
longLong64 位有符号整数,取值范围是 -9223372036854775808 到 9223372036854775807。需要注意的是,在给 long 类型的变量赋值时,如果值超过了 int 的范围,需要在数字后面加上 L 或 l,例如 long num = 1234567890123L;

浮点类型

基本数据类型包装类描述
floatFloat单精度 32 位浮点数。在给 float 类型的变量赋值时,需要在数字后面加上 F 或 f,例如 float num = 3.14F;
doubleDouble双精度 64 位浮点数,是 Java 中默认的浮点类型,例如 double num = 3.14;

字符类型

基本数据类型包装类描述
charCharacter表示单个 16 位 Unicode 字符,用单引号括起来,例如 char c = 'A';

布尔类型

基本数据类型包装类描述
booleanBoolean表示布尔值,只有两个取值:true 和 false

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词