达内javaSE_day17 学习笔记 ——泛型、Stream、集合(List、Set、Map)
程序员文章站
2022-05-25 21:15:58
...
javaSE_day17
1. 泛型
什么是泛型
java泛型设计原则:编译不出错,运行时不会出现ClassCastException
1.1 泛型类
在类上定义的泛型,在方法中也可以使用
1.2 泛型方法
1.3 泛型类派生出的子类
- 子类明确泛型类的类型参数变量
- 子类不明确泛型类的类型参数变量
eg:
以接口为例:泛型接口
List 和 List不存在继承关系
1.4 泛型的使用 – 通配符 “?”
? 表示任意数据类型
设置通配符的上限、下限
- List<? extends Animal> list
- List<? super Number> list
通配符的错误使用
- class A<?>{}
- public <?> void t(List<?> list){}
- List<?> list = new ArrayList<?>();
2. Stream
和io没有任何关系
2.1 流式思想
- 像生产流水线一样,一个操作接一个操作。
- 使用流操作集合更高效
2.2 stream的特性
- stream不存储数据
- stream不改变源数据
- stream的延迟执行特性
2.3使用Stream流的步骤
数据源 → 转换成流 → 操作1 → 操作2 →……
2.3.1 数据源(source)
可以是集合、数组等。
2.3.2 获取流
- Stream streamStr = liststr .stream();//把集合变成流
- Stream streamInt = Stream.of(num);//把数组变成流
Stream只能被使用一次,如果还想使用,必须重新获取流。
如果不重新获取,会得到异常:stream has already been operated upon or closed
2.6 常用方法
-
filter(): 用于通过设置的条件过滤出元素
延迟执行,不立刻执行,遇到终结性方法时才执行 - map(): 用于映射每个元素到对应的结果
- limit(): 用于获取指定数量的流
- 跳过前n个stream.skip
- 流的连接Stream.concat(stream1,stream2)
- 返回数量count 终结性方法
- 可以把流转换为 List 类型:collect(Collectors.toList()); 终结性方法
- 求和的方法reduce(0, (x, y) -> x + y)
- distinct(): 去重
- sorted(): 排序
- forEach: 遍历 终结性方法
练习
- 有如下整数1,-2,-3,4,-5,使用Stream取元素绝对值并打印。
public static void test1() {
Stream<Integer> stream = Stream.of(1,-2,-3,4,-5);
stream.forEach(e->System.out.println(Math.abs(e)));
}
- 给定一个数字列表,如何返回一个由每个数的平方构成的列表。给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】。
public static void test2() {
Stream<Integer> stream = Stream.of(1,2,3,4,5);
stream.map(e->e*e).forEach(e->System.out.println(e));
}
- 有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,使用Stream将以郭字开头的元素存入新集合。
public static void test3() {
Stream<String> stream = Stream.of("黄药师","冯衡","郭靖","黄蓉","郭芙","郭襄","郭破虏");
List<String> list = stream.filter(e->e.startsWith("郭")).collect(Collectors.toList());
System.out.println(list);
}
- 已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、武眠风、冯默风、罗玉风},使用Stream
(1)取出前2个元素并在控制台打印输出。
(2)取出后2个元素并在控制台打印输出。
public static void test4() {
List<String> liststr = new ArrayList<>();
liststr.add("陈玄风");liststr.add("梅超风");liststr.add("陆乘风");
liststr.add("曲灵风");liststr.add("武眠风");
liststr.add("冯默风");liststr.add("罗玉风");
Stream<String> streamStr = liststr.stream();
streamStr.limit(2).forEach(e->System.out.println(e));
List<String> liststr2 = new ArrayList<>();
liststr2.add("陈玄风");liststr2.add("梅超风");liststr2.add("陆乘风");
liststr2.add("曲灵风");liststr2.add("武眠风");
liststr2.add("冯默风");liststr2.add("罗玉风");
Stream<String> streamStr2 = liststr2.stream();
streamStr2.skip(liststr2.size()-2).forEach(System.out::println);
}
- 用 map 和 reduce 方法数一数流中有多少个Employee
List emps = Arrays.asList(
new Employee(102, “李四”, 59),
new Employee(101, “张三”, 18),
new Employee(103, “王五”, 28),
new Employee(104, “赵六”, 8),
new Employee(105, “田七”, 38)
);
public static void test5() {
List<Employee> emps = Arrays.asList(
new Employee(102,"李四",59),new Employee(101,"张三",18),new Employee(103,"王五",28),
new Employee(104,"赵六",8),new Employee(105,"田七",38) );
Stream<Employee> stream = emps.stream();
System.out.println(stream.map(e->1).reduce(0,(x,y)->x+y));
}
- 找出2011年发生的所有交易, 并按交易额排序(从低到高)
class Transaction {
private int year; //交易时间
private int value; //交易额
方法。。。。
List transactions =Arrays.asList(
new Transaction(2011, 300),
new Transaction(2012, 1000),
new Transaction(2011, 400),
new Transaction(2012, 710),
new Transaction(2011, 200),
new Transaction(2012, 700),
new Transaction(2012, 950)
);
public static void test6() {
List<Transaction> transactions = Arrays.asList(
new Transaction(2011,300),
new Transaction(2012,1000),
new Transaction(2011,400),
new Transaction(2012,710),
new Transaction(2011,200),
new Transaction(2012,700),
new Transaction(2012,950)
);
transactions.stream().filter(e->e.getYear()==2011).sorted((t1,t2)->t1.getValue()-t2.getValue()).forEach(e->System.out.println(e));
}
3. List集合的实现类
LinkedList 和 Vector
- LinkedList和ArrayList都是线程不安全的
- Vector是线程安全的
4. Set集合
不重复
先判断hashCode(); 若相同,还要判断equals方法,如果返回true,则表示一个对象,否则是不同对象
HashSet 和 TreeSet
- HashSet基于HashMap的实现
- HashSet的元素是map中的key。
- TreeSet的元素必须是有排序规则的对象,否则会运行时异常
5. Map集合
HashMap
集合总结
HashMap | HashSet |
---|---|
实现了Map接口 | 实现了Set接口 |
存储键值对 | 仅存储对象 |
使用put()方法将元素放入map中 | 使用add()方法将元素放入set中 |
使用键对象来计算hashcode值 | 使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false |
比较快,因为是使用唯一的键来获取对象 | HashSet较HashMap来说比较慢 |
有序 | 线程安全 | 原理及特性 | 线程同步 | 适用场景 | |
---|---|---|---|---|---|
Map | 无序 | 否 | 1.是一个接口 2.主要用于存储键值对(key-value的形式),不允许键重复,允许值重复 | 否 | |
HashMap | 无序 | 否 | 1. 原理:实现了Map接口的实现类,基于hashing原理,通过put()和get()方法存储和获取对象。将键值对传递给put()方法时,调用见对象的hashCode()方法计算hashCode,然后找到bucket位置来存储键值对象。当获取对象时,通过equals()方法找到正确的键值对,然后返回值对象。2. HashMap的遍历速度和他的容量有关。3. HashMap底层是基于数组+链表。4. “碰撞”:当两个不同的键对象的hashcode相同时, 它们会储存在同一个bucket位置的链表中,Entry(包含有键值对的Map.Entry对象)会存储在链表中。使用键对象的equals()方法用来找到键值对。 | 否 | 在Map 中插入、删除和定位元素,HashMap 是最好的选择 |
TreeMap | 有序 | 否 | 1. 实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。2. 对元素进行整体的自然排序,需要元素对应的类实现。3. 如果需要给某个TreeSet对象单独制定比较规则,则使用Comparable;若不指定,则使用Comparable进行整体的自然排序 | 否 | 自然顺序或自定义顺序遍历键,那么TreeMap会更好 |
set | 无序 | 否 | Set的集合里不允许对象有重复的值 | 否 | |
HashSet | 无序 | 否 | 1. 实现了Set接口,不允许集合中有重复的值。2. 在对象存储在HashSet之前要确保对象重写equals()和hashCode()方法,比较对象的值是否相等,以确保Set中没有存储相等的对象,若不重写,则使用该方法的默认实现。 | 否 | |
List | 有序 | 否 | 1list是接口。List允许有重复,它对集合中的对象进行索引。通过下标对指定位置上的元素进行操作 | 否 | 快速插入和删除 |
LinkList | 有序 | 否 | 基于节点(Node)来实现的。利用节点来存储数据以及维系链表之间每一个节点的关系。内存空间不连续。 | 否 | 便于增删改 |
ArrayList | 有序 | 否 | 1. 用数组实现的List的实现类2. 内存空间连续 | 否 | 便于查询 |
Vector | 有序 | 是 | 1.依靠数组来存储数据,每次扩容默认增加一倍。 | 是 | 快速查找 |
上一篇: 达内javaSE_day21—— 服务器v5-v9
下一篇: Java之HashMap的工作原理