Java基础 - 9 - 集合进阶(二)

一. Collection的其他相关知识

1.1 可变参数

可变参数就是一种特殊形参,定义在方法、构造器的形参列表里,格式是:数据类型…参数名称;

可变参数的特点和好处

特点:可以不传数据给它;可以传一个或者同时传多个数据给它;也可以传一个数组给它

好处:常常用来灵活的接收数据

//demo
public class demo{public static void main(String[] args){//可变参数特点method();  //不传数据method(10);  //传一个数据method(10,20,30);  //传多个数据method(new int[]{1,2,3,4,5});  //传一个数组给可变参数}//注意事项1:一个形参列表中,只能有一个可变参数//注意事项2:可变参数必须放在形参列表的最后面public static void method(int...nums){//可变参数在方法内部本质就是一个数组System.out.println(nums.length);System.out.println(Arrays.toString(nums));System.out.println("====================");}
}

1.2 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<?> list)对List集合中的元素进行升序排序
public static <T> void sort(List<?> list , Comparator<? super T>c)对List集合中元素,按照比较器对象指定的规则进行排序

//demo
public class demo{public static void main(String[] args){//<? super T> 接收子类及其父类的类型//public static <T> boolean addAll(Collection<? super T>c , T…elements)	给集合批量添加元素List<String> names = new ArrayList<>();Collections.addAll(names,"张三","李四","王五","二麻子");  //批量添加,不用再一个个add了System.out.println(names); //[张三, 李四, 王五, 二麻子]//public static void shuffle(List<?> list)	打乱List集合中的元素顺序(List是有序、可重复、有索引)Collections.shuffle(names);System.out.println(names); //[二麻子, 王五, 张三, 李四]//public static <T> void sort(List<?> list)	对List集合中的元素进行升序排序List<Integer> nums = new ArrayList<>();Collections.addAll(nums,1,3,7,5,2);System.out.println(nums); //[1, 3, 7, 5, 2]Collections.sort(nums);System.out.println(nums); //[1, 2, 3, 5, 7]List<Car> cars = new ArrayList<>();Car c1 = new Car("奔驰",12.8);Car c2 = new Car("宝马",14.1);Car c3 = new Car("大众",9.9);Car c4 = new Car("未来",14.1);Collections.addAll(cars,c1,c2,c3,c4);System.out.println(cars); //[Car{name='奔驰', price=12.8}, Car{name='宝马', price=14.1}, Car{name='大众', price=9.9}, Car{name='未来', price=14.1}]//编译时异常(标红报错):因为sort不知道自定义对象按照什么规则排序//修改方式:让Car类实现Comparable(比较规则)接口,然后重写compareTo方法来指定比较规则//Collections.sort(cars);//System.out.println(cars); //[Car{name='大众', price=9.9}, Car{name='奔驰', price=12.8}, Car{name='宝马', price=14.1}, Car{name='未来', price=14.1}]//public static <T> void sort(List<?> list , Comparator<? super T>c) 对List集合中元素,按照比较器对象指定的规则进行排序Collections.sort(cars, new Comparator<Car>() {@Overridepublic int compare(Car o1, Car o2) {//return Double.compare(o1.getPrice(),o2.getPrice());  //升序return Double.compare(o2.getPrice(),o1.getPrice());  //降序}});System.out.println(cars);}
}//Car
public class Car implements Comparable<Car> {private String name;private double price;//this代表主调   o是被调@Overridepublic int compareTo(Car o) {//如果认为左边对象大于右边对象返回正整数//如果认为左边对象小于右边对象返回负整数//如果认为左边对象等于右边对象返回0//需求:按照价格升序排序//return (int)(this.price-o.price); //不能这样写,返回值是int类型,两个double类型相减之后强转可能会出bug//写法1
//        if(this.price>o.price){
//            return 1;
//        }else if(this.price<o.price){
//            return -1;
//        }else{
//            return 0;
//        }//写法2return Double.compare(this.price,o.price);}//右键->生成->equals()和hashCode()@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Car car = (Car) o;return Double.compare(car.price, price) == 0 &&Objects.equals(name, car.name);}@Overridepublic int hashCode() {return Objects.hash(name, price);}public Car() {}public Car(String name, double price) {this.name = name;this.price = price;}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;}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", price=" + price +'}';}
}

1.3 综合案例 

//demo
public class demo {public static void main(String[] args) {//创建房间Room r = new Room();//启动游戏r.start();}
}//Room
public class Room {//必须有一副牌private List<Card> allCards = new ArrayList<>();public Room(){//做出54张牌,存入到集合allCards中//点数String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};//花色String[] colors = {"♣","♦","♠","♥"};//遍历点数后再遍历花色,组织成牌for (int i = 0; i < numbers.length; i++) {  //i不仅仅是numbers数组的索引,因为点数是按升序放在里面,所以正好还可以代表牌的大小for (int j = 0; j < colors.length; j++) {Card card = new Card(numbers[i],colors[j],i);  //创建牌对象allCards.add(card);  //存到集合中}}//单独存放大小王Card c1 = new Card("","👨",14); //大王Card c2 = new Card("","👩",13); //小王Collections.addAll(allCards,c1,c2); //存到集合中System.out.println("一副新牌:"+allCards);}//启动游戏public void start() {//洗牌Collections.shuffle(allCards);//创建三个玩家的手牌集合List<Card> user1 = new ArrayList<>();List<Card> user2 = new ArrayList<>();List<Card> user3 = new ArrayList<>();//发牌//最后要剩余三张for (int i = 0; i < allCards.size() - 3; i++) {if(i%3==0){user1.add(allCards.get(i));}else if(i%3==1){user2.add(allCards.get(i));}else{user3.add(allCards.get(i));}}//给玩家的牌进行降序排序sortCards(user1);sortCards(user2);sortCards(user3);//玩家手牌情况sortCards(user1);System.out.println("玩家1的手牌:" + user1);System.out.println("玩家2的手牌:" + user2);System.out.println("玩家3的手牌:" + user3);//底牌//System.out.println("底牌:" + allCards.get(51) + allCards.get(52) + allCards.get(53));List<Card> diPai = allCards.subList(allCards.size()-3,allCards.size()); //截取集合的最后三个元素System.out.println("底牌:" + diPai);//抢地主(假设抢地主的规则是:随机生成0 1 2,匹配地主)Random r = new Random();int diZhu = r.nextInt(3); //随机生成0,1,2if(diZhu==0){user1.addAll(diPai);sortCards(user1);System.out.println("玩家1抢地主后的手牌是:" + user1);}else if (diZhu==1){user2.addAll(diPai);sortCards(user2);System.out.println("玩家2抢地主后的手牌是:" + user2);}else{user3.addAll(diPai);sortCards(user3);System.out.println("玩家3抢地主后的手牌是:" + user3);}}private void sortCards(List<Card> user) {Collections.sort(user, new Comparator<Card>() {@Overridepublic int compare(Card o1, Card o2) {//return o1.getSize() - o2.getSize(); //升序排列return o2.getSize() - o1.getSize(); //降序排列}});}
}//Card
public class Card {private String number;private String color;//每张牌存在大小private int size; //0,1,2……public Card() {}public Card(String number, String color, int size) {this.number = number;this.color = color;this.size = size;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}@Overridepublic String toString() {return color + number;}
}

二. Map集合

· Map集合称为双列集合,格式:{key1=value1,key2=value2,key3=value3,…},一次需要存一对数据作为一个元素

· Map集合的每个元素“key=value”称为一个键值对/键值对对象/一个Entry对象,Map集合也被叫做“键值对集合

· Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值

Map集合的应用场景

        需要存储一一对应的数据时,就可以考虑使用Map集合来做

Map集合体系

Map集合体系的特点

注意:Map系列集合的特点都是由键决定的,值知识一个附属品,值是不做要求的

· HashMap(由键决定特点):无序、不重复、无索引(用的最多)

· LinkedHashMap(由键决定特点):有序、不重复、无索引

· TreeMap(由键决定特点):按照键的大小默认升序排序、不重复、无索引

//demo
public class demo{public static void main(String[] args){Map<String, Integer> map = new HashMap<>(); //多态map.put("哇哈哈",3);map.put("哇哈哈",2);  //重复数据(键重复),后加的数据会覆盖前加的map.put("冰红茶",3);map.put("农夫山泉",2);map.put(null,null);System.out.println(map);  //{null=null, 农夫山泉=2, 冰红茶=3, 哇哈哈=2} 无序,不重复,无索引Map<String, Integer> map2 = new LinkedHashMap<>(); //多态map2.put("哇哈哈",3);map2.put("哇哈哈",2);  //重复数据(键重复),后加的数据会覆盖前加的map2.put("冰红茶",3);map2.put("农夫山泉",2);map2.put(null,null);System.out.println(map2);  //{哇哈哈=2, 冰红茶=3, 农夫山泉=2, null=null} 有序,不重复,无索引Map<Integer,String> map3 = new TreeMap<>(); //多态map3.put(1,"哇哈哈");map3.put(2,"哇哈哈");  //重复数据(键重复),后加的数据会覆盖前加的map3.put(3,"冰红茶");map3.put(4,"农夫山泉");System.out.println(map3);  //{1=哇哈哈, 2=哇哈哈, 3=冰红茶, 4=农夫山泉} 按照大小默认升序排序、不重复、无索引}
}

2.1 Map集合常用方法 

        Map是双列集合的祖宗,它的功能是全部双列集合都可以继承过来使用的

方法名称说明
public V put(K key,V value)添加元素
public int size()获取集合的大小
public void clear()清空集合
public boolean isEmpty()判断集合是否为空,为空返回true,反之返回false
public V get(Object key)根据键获取对应值
public V remove(Object key)根据键删除整个元素(删除键会返回键的值)
public boolean containsKey(Object key)判断是否包含某个键,包含返回true,反之返回false
public boolean containsValue(Object value)判断是否包含某个值

public Set<K> keySet()

获取Map集合的全部键
public Collection<V> values()获取Map集合的全部值
//demo
public class demo{public static void main(String[] args){Map<String, Integer> map = new HashMap<>(); //多态//1.添加元素map.put("哇哈哈",3);map.put("哇哈哈",2);  //重复数据(键重复),后加的数据会覆盖前加的map.put("冰红茶",3);map.put("农夫山泉",2);map.put(null,null);System.out.println(map);  //{null=null, 农夫山泉=2, 冰红茶=3, 哇哈哈=2} 无序,不重复,无索引//2.public int size() 获取集合的大小System.out.println(map.size()); //4//3.public void clear()	清空集合
//        map.clear();
//        System.out.println(map); //{}//4.public boolean isEmpty()	判断集合是否为空,为空返回true,反之返回false
//        System.out.println(map.isEmpty()); //true//5.public V get(Object key)	根据键获取对应值System.out.println(map.get("哇哈哈")); //2System.out.println(map.get("冰红茶")); //3System.out.println(map.get(null)); //nullSystem.out.println(map.get("怡宝")); //null  根据键获取值的时候,如果键不存在,返回值也是null//6.public V remove(Object key)	根据键删除整个元素(删除键会返回键的值)System.out.println(map.remove(null)); //nullSystem.out.println(map); //{农夫山泉=2, 冰红茶=3, 哇哈哈=2}//7.public boolean containsKey(Object key)	判断是否包含某个键,包含返回true,反之返回falseSystem.out.println(map.containsKey("农夫山泉")); //trueSystem.out.println(map.containsKey("怡宝")); //false//8.public boolean containsValue(Object value)	判断是否包含某个值System.out.println(map.containsValue(2)); //trueSystem.out.println(map.containsValue(5)); //falseSystem.out.println(map.containsValue("2")); //false 要精确类型,整型2包含,字符2不包含//9.public Set<K> keySet()	获取Map集合的全部键  返回是set集合(无序 不重复 无索引)System.out.println(map.keySet()); //[农夫山泉, 冰红茶, 哇哈哈]//10.public Collection<V> values()	获取Map集合的全部值 返回是Collection集合(因为键值对的值是可重复)System.out.println(map.values()); //[2, 3, 2]//11.把其他Map集合的数据倒入到自己集合中来Map<String,Integer> map1 = new HashMap<>();map1.put("绿茶",3);map1.put("元气森林",5);Map<String,Integer> map2 = new HashMap<>();map2.put("脉动",5);map2.put("绿茶",4);System.out.println(map1); //{绿茶=3, 元气森林=5}System.out.println(map2); //{脉动=5, 绿茶=4}map1.putAll(map2); //把map2集合中的元素全部倒入一份到map1集合中去(map2不会改变,相当于把map2的数据复制了一份给map1)System.out.println(map1); //{脉动=5, 绿茶=4, 元气森林=5}System.out.println(map2); //{脉动=5, 绿茶=4}}
}

2.2 Map集合遍历方式

2.2.1 键找值

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

2.2.2 键值对

        把键值对堪称一个整体进行遍历

2.2.3 Lambda表达式

        JDK1.8开始之后的新技术

//demo
public class demo{public static void main(String[] args){Map<String, Double> map = new HashMap<>(); //多态//添加元素map.put("哇哈哈",3.0);map.put("哇哈哈",2.0);  //重复数据(键重复),后加的数据会覆盖前加的map.put("冰红茶",3.0);map.put("农夫山泉",2.5);map.put("脉动",5.5);System.out.println(map);  //{脉动=5.5, 农夫山泉=2.5, 冰红茶=3.0, 哇哈哈=2.0} 无序,不重复,无索引System.out.println("-----------------------------");//Map集合遍历方式1——键找值//先获取Map集合全部的键Set<String> keys_Set = map.keySet();System.out.println(keys_Set); //[脉动, 农夫山泉, 冰红茶, 哇哈哈]//再通过遍历键来找值,根据键获取其对应的值for (String s : keys_Set) {double value = map.get(s);System.out.println(s+" "+value+"元");}System.out.println("-----------------------------");//Map集合遍历方式2——键值对//把键值对堪称一个整体进行遍历//输入map.entrySet()后直接ctrl+alt+v 生成 Set<Map.Entry<String, Double>> entries = map.entrySet();Set<Map.Entry<String, Double>> entries = map.entrySet();System.out.println(entries); //[脉动=5.5, 农夫山泉=2.5, 冰红茶=3.0, 哇哈哈=2.0]for (Map.Entry<String, Double> entry : entries) {String key = entry.getKey();double value = entry.getValue();System.out.println(key+" "+value+"元");}System.out.println("-----------------------------");//Map集合遍历方式3——Lambda表达式//JDK1.8开始之后的新技术map.forEach(new BiConsumer<String, Double>() {@Overridepublic void accept(String s, Double aDouble) {System.out.println(s+" "+aDouble+"元");}});//简化System.out.println("-----------------------------");map.forEach((s,aDouble) -> System.out.println(s+" "+aDouble+"元"));  //map.forEach((k,v) -> System.out.println(k+" "+v+"元"));}
}

2.2.4 案例

//demo
public class demo{public static void main(String[] args){List<Character> list = new ArrayList<>();  //用一个list存放学生的投票结果Random r = new Random();for (int i = 0; i < 80; i++) {int choose = r.nextInt(4); //随机生成整数0,1,2,3switch (choose){case 0:list.add('A');break;case 1:list.add('B');break;case 2:list.add('C');break;case 3:list.add('D');break;default:System.out.println("学生的选择不存在~~~");}}System.out.println(list);Map<Character,Integer> map = new HashMap<>(); //创建一个map集合存放投票统计结果for (int i = 0; i < list.size(); i++) {char key = list.get(i);  //用key保存当前的字符//判断是否包含某个键(c的值)if(map.containsKey(key)){  //包含(说明这个景点统计过)map.put(key,map.get(key)+1); //get方法返回的是键对应的值}else{ //不包含(说明这个景点没统计过)map.put(key,1);}}System.out.println(map);}
}

2.3 HashMap

HashMap集合的特点

        HashMap(由键决定特点):无序、不重复、无索引(用的最多)

HashMap集合的底层原理

        HashMap跟HashSet的底层原理是一致的,都是基于哈希表实现的(实际上,Set系列集合的底层就是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据

        HashMap集合是一种增删改查数据,性能都较好的集合

        HashMap的键依赖hashCode方法和equals方法保证键的唯一

        如果键存储的是自定义类型的对象,可以通过重写hashCode和equals方法,这样可以保证多个对象内容一样时,HashMap集合就能认为是重复的

哈希表

        JDK8之前,哈希表=数组+链表

        JDK8开始,哈希表=数组+链表+红黑树

         哈希表是一种增删改查数据,性能都较好的数据结构

//demo
public class demo{public static void main(String[] args){Map<Car,String> map = new HashMap<>();map.put(new Car("奔驰",13.14),"made in C");map.put(new Car("奔驰",13.14),"made in H");map.put(new Car("宝马",13.13),"made in C");System.out.println(map);//如果不重写HashCode方法和equals方法,会保存两个Car{name='奔驰', price=13.14}数据//{Car{name='奔驰', price=13.14}=made in H, Car{name='奔驰', price=13.14}=made in C, Car{name='宝马', price=13.13}=made in C}//重写后//{Car{name='宝马', price=13.13}=made in C, Car{name='奔驰', price=13.14}=made in H}}
}//Car
public class Car implements Comparable<Car> {private String name;private double price;//this代表主调   o是被调@Overridepublic int compareTo(Car o) {//如果认为左边对象大于右边对象返回正整数//如果认为左边对象小于右边对象返回负整数//如果认为左边对象等于右边对象返回0//需求:按照价格升序排序//return (int)(this.price-o.price); //不能这样写,返回值是int类型,两个double类型相减之后强转可能会出bug//写法1
//        if(this.price>o.price){
//            return 1;
//        }else if(this.price<o.price){
//            return -1;
//        }else{
//            return 0;
//        }//写法2return Double.compare(this.price,o.price);}//右键->生成->equals()和hashCode()@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Car car = (Car) o;return Double.compare(car.price, price) == 0 &&Objects.equals(name, car.name);}@Overridepublic int hashCode() {return Objects.hash(name, price);}public Car() {}public Car(String name, double price) {this.name = name;this.price = price;}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;}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", price=" + price +'}';}
}

2.4 LinkedHashMap

LinkedHashMap集合的特点

        LinkedHashMap(由键决定特点):有序、不重复、无索引

LinkedHashMap集合的底层原理

        LinkedHashMap集合也是基于哈希表(数组、链表、红黑树)实现的,但是它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置(保证有序

        实际上,LinkedHashSet集合的底层原理就是LinkedHashMap

2.5 TreeMap

TreeMap集合的特点

        TreeMap(由键决定特点):按照键的大小默认升序排序(只能对键排序)、不重复、无索引

TreeMap集合的底层原理

        TreeMap和TreeSet集合的底层原理是一样的,都是基于红黑树实现的排序

注意:

        · 对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序

        · 对于字符串类型:默认按照首字符的编号升序排序

        · 对于自定义类型如Student对象,TreeSet默认是无法直接排序的

TreeMap集合支持两种方式来指定排序规则

方式一

· 让自定义的类实现Comparable接口重写里面的compareTo方法来指定比较规则

方式二

· 通过调用TreeSet集合有参数构造器,可以设置Comparator对象(比较器对象),用于指定比较规则

        public TreeSet(Comparator<? super E> comparator)

//demo
public class demo{public static void main(String[] args){Map<Car,String> map = new TreeMap<>(new Comparator<Car>() {@Overridepublic int compare(Car o1, Car o2) {return Double.compare(o2.getPrice(),o1.getPrice());  //降序}});// Map<Car,String> map = new TreeMap<>((o1, o2) -> Double.compare(o2.getPrice(),o1.getPrice()));map.put(new Car("奔驰",13.14),"made in C");map.put(new Car("奔驰",13.14),"made in H");map.put(new Car("宝马",13.13),"made in C");System.out.println(map);//对于自定义类型,TreeSet默认是无法直接排序的,会产生ClassCastException异常//升序:{Car{name='宝马', price=13.13}=made in C, Car{name='奔驰', price=13.14}=made in H}//降序:{Car{name='奔驰', price=13.14}=made in H, Car{name='宝马', price=13.13}=made in C}}
}//Car
public class Car implements Comparable<Car> {private String name;private double price;//this代表主调   o是被调@Overridepublic int compareTo(Car o) {//如果认为左边对象大于右边对象返回正整数//如果认为左边对象小于右边对象返回负整数//如果认为左边对象等于右边对象返回0//需求:按照价格升序排序return Double.compare(this.price,o.price);}//右键->生成->equals()和hashCode()@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Car car = (Car) o;return Double.compare(car.price, price) == 0 &&Objects.equals(name, car.name);}@Overridepublic int hashCode() {return Objects.hash(name, price);}public Car() {}public Car(String name, double price) {this.name = name;this.price = price;}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;}@Overridepublic String toString() {return "Car{" +"name='" + name + '\'' +", price=" + price +'}';}
}

2.6 集合的嵌套

        集合的嵌套指的是集合中的元素又是一个集合

//demo
public class demo{public static void main(String[] args){Set<String> set1 = new HashSet<>();
//        set1.add("南京市");
//        set1.add("扬州市");
//        set1.add("苏州市");//用Collection批量加入Collections.addAll(set1,"南京市","扬州市","苏州市");Set<String> set2 = new HashSet<>();
//        set2.add("武汉市");
//        set2.add("宜昌市");
//        set2.add("鄂州市");Collections.addAll(set2,"武汉市","宜昌市","鄂州市");Map<String,Set<String>> map = new HashMap<>();map.put("江苏省",set1);map.put("湖北省",set2);System.out.println(map);System.out.println("湖北省:"+map.get("湖北省"));//Lambda表达式 遍历map.forEach((k,v) -> System.out.println(k+":"+v));}
}

三. Stream流

        Stream也叫Stream流,是JDK8开始新增的一套API(java.util.stream.*),可以用于操作集合或者数组的数据

优势:Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好

//demo
public class demo{public static void main(String[] args){List<String> names = new ArrayList<>();Collections.addAll(names,"张三","李四","张二二","王五","张老六");System.out.println(names);  //[张三, 李四, 张二二, 王五, 张老六]//找出姓张,且是3个字的名字,存入到一个新集合中List<String> name_Zhang = new ArrayList<>();for (String name : names) {if(name.startsWith("张") && name.length()==3){name_Zhang.add(name);}}System.out.println(name_Zhang); //[张二二, 张老六]//用Stream流实现List<String> name_Z = names.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==3).collect(Collectors.toList());System.out.println(name_Z); //[张二二, 张老六]}
}

3.1 获取Stream流

        获取集合的Stream流

Collection提供的方法说明
default Stream<E> stream()获取当前集合对象的Stream流

        获取数组的Stream流

Arrays类提供的方法说明
public static <T> Stream<T> stream(T[] array)获取当前数组的Stream流
Stream类提供的方法说明
public static <T> Stream<T> of(T… values)获取当前接收数据的Stream流
//demo
public class demo{public static void main(String[] args){//List集合的Stream流List<String> names1 = new ArrayList<>();Collections.addAll(names1,"张三","李四","张二二","王五","张老六");System.out.println(names1);  //[张三, 李四, 张二二, 王五, 张老六]Stream<String> stream1 = names1.stream();stream1.filter(s -> s.length()==2).forEach(s -> System.out.println(s));System.out.println("====================================");//Set集合的Stream流Set<String> names2 = new HashSet<>();Collections.addAll(names2,"周一","周二","周三","周末","小周");System.out.println(names2);  //[周一, 小周, 周末, 周三, 周二]Stream<String> stream2 = names2.stream();stream2.filter(s -> s.startsWith("周")).forEach(s -> System.out.println(s));System.out.println("====================================");//Map集合的Stream流Map<String,Double> map = new HashMap<>();map.put("哇哈哈",3.0);map.put("冰红茶",3.0);map.put("农夫山泉",2.5);map.put("脉动",5.5);System.out.println(map);  //{脉动=5.5, 农夫山泉=2.5, 冰红茶=3.0, 哇哈哈=3.0}//不能直接map.stream(),因为stream()方法是Collection提供的Set<String> keys = map.keySet();Stream<String> ks = keys.stream();Collection<Double> values = map.values();Stream<Double> vs = values.stream();Set<Map.Entry<String, Double>> entries = map.entrySet();Stream<Map.Entry<String, Double>> kvs = entries.stream();kvs.filter(e -> e.getKey().contains("哈")).forEach(s -> System.out.println(s));System.out.println("====================================");//数组的Stream流String[] names3 = {"Nike","Nim","Mike","Helen"};System.out.println(Arrays.toString(names3));Stream<String> stream3 = Arrays.stream(names3);Stream<String> stream3_1 = Stream.of(names3);stream3.filter(s->s.contains("i")).forEach(s-> System.out.println(s));System.out.println("====================================");stream3_1.filter(s->s.length()==5).forEach(s-> System.out.println(s));}
}

3.2 Stream流常见的中间方法

        中间方法指的是调用完成后会返回新的Stream流,可以继续使用(支持链式编程)

Stream提供的常用中间方法说明
Stream<T> filter(Predicate<? super T> predicate)用于对流中的数据进行过滤
Stream<T> sorted()对元素进行升序排序
Stream<T> sorted(Comparator<? super T> comparator)按照指定规则排序
Stream<T> limit(long maxSize)获取前几个元素
Stream<T> skip(long n)跳过前几个元素
Stream<T> distinct()去除流中重复的元素
<R> Stream<R> map(Function<? super T , ? extends R> mapper)对元素进行加工,并返回对应的新流
static <T> Stream<T> concat(Stream a , Stream b)合并a和b两个流为一个流
//demo
public class demo{public static void main(String[] args){List<Double> prices = new ArrayList<>();Collections.addAll(prices,12.13,13.0,15.0,17.0,15.4,11.0);//需求:找出价格超过15的数据,并升序排序,再输出prices.stream().filter(s -> s>=15).sorted().forEach(s -> System.out.println(s));System.out.println("========================================");List<Student> students = new ArrayList<>();Student s1 = new Student("张三","男",79,22);Student s2 = new Student("张三","男",79,22);Student s3 = new Student("李四","男",89.5,21);Student s4 = new Student("王五","男",98,21);Student s5 = new Student("小美","女",57.5,21);Student s6 = new Student("小新","女",100,20);Student s7 = new Student("小海","男",88,19);Collections.addAll(students,s1,s2,s3,s4,s5,s6,s7);//需求:找出成绩在85-95(包括85和95)之间的学生,并按照成绩降序排序students.stream().filter(s -> s.getScore()>=85 && s.getScore()<=95).sorted((o1, o2) -> Double.compare(o2.getScore(),o1.getScore())).forEach(s -> System.out.println(s));System.out.println("========================================");//需求:取出成绩前三的学生,并输出//先按照成绩降序排序再取出前三名students.stream().sorted((o1,o2)->Double.compare(o2.getScore(),o1.getScore())).limit(3).forEach(s -> System.out.println(s));System.out.println("========================================");//需求:取出年纪最小的两个学生,并输出students.stream().sorted((o1,o2) -> o1.getAge()-o2.getAge()).limit(2).forEach(s -> System.out.println(s));System.out.println("========================================");//需求:取出年纪最大的两个学生,并输出students.stream().sorted((o1,o2) -> o1.getAge()-o2.getAge()).skip(students.size()-2).forEach(s -> System.out.println(s));System.out.println("========================================");//需求:找出年纪大于20岁的学生叫什么名字,要求去除重复名字,再输出students.stream().filter(s -> s.getAge() > 20).map(s -> s.getName())   //把这个流加工成只剩下名字.distinct().forEach(s -> System.out.println(s));//distinct去重复,针对自定义类型的对象,如果希望内容一样就认为重复,需要重写HashCode和equals方法,不重写就不会去重复students.stream().filter(s -> s.getAge() > 20).distinct().forEach(s -> System.out.println(s));Stream<String> st1 = Stream.of("张三","李四");  //Stream.of()获取数组的stream流Stream<String> st2 = Stream.of("王五","李四");Stream.concat(st1,st2).forEach(System.out::println);Stream<Integer> st3 = Stream.of(1,2,3);Stream<Double> st4 = Stream.of(5.2,7.7);Stream.concat(st3,st4).forEach(System.out::println);}
}//Student
public class Student {private String name;  //姓名private String sex;  //性别private double score;  //成绩private int age;  //年龄public Student() {}public Student(String name, String sex, double score, int age) {this.name = name;this.sex = sex;this.score = score;this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Double.compare(student.score, score) == 0 &&age == student.age &&Objects.equals(name, student.name) &&Objects.equals(sex, student.sex);}@Overridepublic int hashCode() {return Objects.hash(name, sex, score, age);}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", score=" + score +", age=" + age +'}';}
}

3.3 Stream流常见的终结方法

        终结方法指的是调用完成后,不会返回新Stream了,没有继续使用流了

Stream提供的常用终结方法说明
void forEach(Consumer action)对此流运算后的元素执行遍历
long count()统计此流运算后的元素个数
Optional<T> max(Comparator<? super T> comparator)获取此流运算后的最大值元素
Optional<T> min(Comparator<? super T> comparator)获取此流运算后的最小值元素

收集Stream流

        收集Stream流就是把Stream流操作后的结果转回到集合或者数组中去返回

        Stream流:方便操作集合/数组的手段;  集合/数组:才是开发中的目的

Stream提供的常用终结方法说明
R collect(Collector collector)把流处理后的结果收集到一个指定的集合中去
Object[] toArray()把流处理后的结果收集到一个数组中去
Collectors工具类提供的具体的收集方法说明
public static <T> Collector toList()把元素收集到List集合中
public static <T> Collector toSet()把元素收集到Set集合中
public static Collector toMap(Function keyMapper , Function valueMapper)把元素收集到Map集合中
//demo
public class demo{public static void main(String[] args){List<Student> students = new ArrayList<>();Student s1 = new Student("张三","男",79,22);Student s2 = new Student("张三","男",79,22);Student s3 = new Student("李四","男",89.5,21);Student s4 = new Student("王五","男",98,21);Student s5 = new Student("小美","女",57.5,21);Student s6 = new Student("小新","女",100,20);Student s7 = new Student("小海","男",88,19);Collections.addAll(students,s1,s2,s3,s4,s5,s6,s7);//需求:计算出成绩>=90的学生人数//long count()	统计此流运算后的元素个数long sum = students.stream().filter(s -> s.getScore()>=90).count();System.out.println(sum);  //2//需求:找出成绩最高的学生对象并输出//Optional<T> max(Comparator<? super T> comparator)	获取此流运算后的最大值元素Optional<Student> o_max = students.stream().max((o1, o2) -> Double.compare(o1.getScore(),o2.getScore()));System.out.println(o_max); //Optional[Student{name='小新', sex='女', score=100.0, age=20}]System.out.println(o_max.get()); //Student{name='小新', sex='女', score=100.0, age=20}//需求:找出成绩最低的学生对象并输出//Optional<T> min(Comparator<? super T> comparator)	获取此流运算后的最小值元素Optional<Student> o_min = students.stream().min((o1, o2) -> Double.compare(o1.getScore(),o2.getScore()));System.out.println(o_min.get()); //Student{name='小美', sex='女', score=57.5, age=21}//收集Stream流//需求:找出成绩在75-90之间的学生对象,并放到一个新集合中去返回//流只能收集一次//放到List集合中List<Student> list = students.stream().filter(s -> s.getScore()>75 && s.getScore()<90).collect(Collectors.toList());System.out.println(list);//[Student{name='张三', sex='男', score=79.0, age=22}, Student{name='张三', sex='男', score=79.0, age=22}, Student{name='李四', sex='男', score=89.5, age=21}, Student{name='小海', sex='男', score=88.0, age=19}]//放到Set集合中Set<Student> set = students.stream().filter(s -> s.getScore()>75 && s.getScore()<90).collect(Collectors.toSet());System.out.println(set);//[Student{name='李四', sex='男', score=89.5, age=21}, Student{name='张三', sex='男', score=79.0, age=22}, Student{name='小海', sex='男', score=88.0, age=19}]//Set中去把两个张三去重了(因为重写了HashCode和equals方法,不重写则不去重)//需求:找出成绩在75-90之间的学生对象,并把学生对象的名字和成绩,存放到一个Map集合中返回Map<String, Double> map = students.stream().filter(s -> s.getScore() > 75 && s.getScore() < 90).distinct().collect(Collectors.toMap(k -> k.getName(), v -> v.getScore()));System.out.println(map); //{李四=89.5, 张三=79.0, 小海=88.0}Object[] objects = students.stream().filter(s -> s.getScore() > 75 && s.getScore() < 90).toArray();System.out.println(Arrays.toString(objects));Student[] stu = students.stream().filter(s -> s.getScore() > 75 && s.getScore() < 90).toArray(len -> new Student[len]);System.out.println(Arrays.toString(stu));}
}//Student
public class Student {private String name;  //姓名private String sex;  //性别private double score;  //成绩private int age;  //年龄public Student() {}public Student(String name, String sex, double score, int age) {this.name = name;this.sex = sex;this.score = score;this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Double.compare(student.score, score) == 0 &&age == student.age &&Objects.equals(name, student.name) &&Objects.equals(sex, student.sex);}@Overridepublic int hashCode() {return Objects.hash(name, sex, score, age);}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", score=" + score +", age=" + age +'}';}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/544320.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Web MVC入门(2)

学习Spring MVC Postman介绍 在软件工程中, 我们需要具有前后端分离的思想, 以降低耦合性. 但是在测试后端代码时,我们还得写前端代码测试,这是个令人头疼的问题. 那么我们如何测试自己的后端程序呢, 这就用到了一个工具: Postman. 界面介绍: 传参的介绍 1.普通传参, 也就…

MongoDB——linux中yum命令安装及配置

一、创建mongodb-org-3.4.repo文件 vi /etc/yum.repos.d/mongodb-org-3.4.repo 将下面内容添加到创建的文件中 [mongodb-org-3.4] nameMongoDB Repository baseurlhttps://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/3.4/x86_64/ gpgcheck1 enabled1 gpgkeyhttps://www…

Linux服务器(Debian系)包含UOS安全相关巡检shell脚本

#!/bin/bash# Define output file current_date$(date "%Y%m%d") # Gets the current date in YYYYMMDD format output_file"server_security_inspection_report_${current_date}.txt"# Empty the file initially echo > $output_file# 获取巡检时间 (…

Qt 实现 Asterix 报文解析库

【写在前面】 最近工作中需要解析 Cat 21 和 Cat 62 的 ADS-B 数据 ( 自己的工作包含航空领域 )。 然后&#xff0c;因为整个 Asterix 协议类别非常之多&#xff0c;每个类别的版本也多&#xff0c;纯手工实现每个版本解析根本不现实 ( 然鹅公司之前的解析库就是这么做的且做的…

MySQL语法分类 DDL(1)

DDL&#xff08;1&#xff09;(操作数据库、表) 数据库操作(CRUD) C(Create):创建 //指定字符集创建 create database db_1 character set utf8;//避免重复创建数据库报错可以用一下命令 create database if not exists db_1 character set utf8;R(Retrieve):查询 //查询所…

C++11:自动类型推导 auto 和 decltype(下)

前面两篇文章分别介绍了 auto 和 decltype&#xff0c;今天聊聊它们两者之间的区别。 语法格式的区别 auto varname value; // auto的语法格式 decltype(exp) varname [ value]; // decltype的语法格式其中&#xff0c;varname 表示变量名&#xff0c;value 表示赋给变量的值…

mybatis源码阅读系列(二)

前言 上一篇文章mybatis源码阅读系列&#xff08;一&#xff09;介绍了mybatis和原生jdbc的区别&#xff0c;并通过代码展示了两者的运行过程和结果&#xff0c;下面让我们继续详细了解下mybatis的执行过程&#xff1b; package com.wyl.mybatis.service;import com.wyl.mybat…

Linux中 vim 编辑器的使用

文章目录 前言一、vim编辑器模式二、简单的插入、保存和退出三、 命令模式下常用命令即其作用1. 命令模式 思维导图 前言 首先&#xff0c;了解一下 什么是vim 编辑器&#xff1f;在不同的系统中&#xff0c;文本的管理也会不同&#xff1b;windos系统就不多说了&#xff0c…

【运维】StarRocks数据迁移到新集群(针对于集群互通、不互通的情况)

文章目录 一. 迁移整体思路1. 对于新旧集群互通的情况2. 对于新旧集群不互通的情况 二、迁移过程&#xff08;两个集群互通的情况&#xff09;1. 备份过程1.1. 通过mysqlclient与starrocks进行关联1.2. 创建仓库与minio建立联系1.3. 备份数据到minio 2. 迁移过程2.1. 通过mysql…

Web核心,HTTP,tomcat,Servlet

1&#xff0c;JavaWeb技术栈 B/S架构:Browser/Server&#xff0c;浏览器/服务器架构模式&#xff0c;它的特点是&#xff0c;客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器&#xff0c;获取Web资源&#xff0c;服务器把Web资源…

【Leetcode】2684. 矩阵中移动的最大次数

文章目录 题目思路代码结果 题目 题目链接&#x1f517; 给你一个下标从 0 开始、大小为 m x n 的矩阵 grid &#xff0c;矩阵由若干 正 整数组成。 你可以从矩阵第一列中的 任一 单元格出发&#xff0c;按以下方式遍历 grid &#xff1a; 从单元格 (row, col) 可以移动到 (…

FPGA和ASIC

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;这是我所总结作为学习的笔记第16篇,在本篇文章给大家介绍FPGA和ASIC。 一个四核i7的CPU的晶体管中有20亿的晶体管&#xff0c;需要链接起20亿的晶体管可不是一件容易的事情&#xff0c;所以设计一个CPU需要用年来算&#x…