可变参数:就是一种特殊形参,定义在方法、构造器的形参列表里
格式:数据类型...参数名称;
特点:可以不传数据给它;可以传一个或者同时传多个数据给它;也可以传一个数组给它
好处:常常用来灵活的接收数据
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:可变参数必须放在形参列表的最后面 (int age,int nums)
Collection:是一个用来操作集合的工具类
方法名称 | 说明 |
public static |
给集合批量添加元察 |
public static void shuffle(List> list) | 打乱List集合中的元素顺序 |
打乱List集合中的元素顺序 | 对List集合中的元素进行升序排序 |
public static |
对List集合中元素,按照比较器对象指定的规则进行排序 |
Collections只支持对List集合进行排序
排序方式1:
方法名称 | 说明 |
public static |
对List集合中元素按照默认规则排序 |
注意:本方法可以直接对自定义类型的List集合排序,但自定义类型必须实现了Comparable接口,指定了比较规则才可以
排序方法2:
方法名称 | 说明 |
public static |
对List集合中元素,按照比较器对象指定的规则进行排序 |
Map集合称为双列集合,格式: {key1=value1 , key2=value2, key3=value3 , ...},一次需要存一对数据作为一个元素
Map集合的每个元素“key=value”称为一个键值对/键值对对象/一个Entry对象,Map集合也被叫做“键值对集合"
Map集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值
考虑一一对应的数据时:需要存储一一对应的数据时,就可以考虑使用Map集合来做
Map集合的特点:
注意:Map系列集合的特点都是由键决定的,值只是一个附属品,值是不做要求的
HashMap(由键决定特点)︰无序、不重复、无索引;(用的最多)
LinkedHashMap (由键决定的特点):有序,不重复,无索引
TreeMap(有键决定特点):按照大小默认升序排序:不重复、无索引
Mapmap=new HashMap<>();//经典代码
map.put("手表",100);
map.put("手表",220);//后面重复的数据会覆盖前面的数据(键)
map.put("书",2);
map.put("Java",2);
map.put(null,null);
System.out.println(map);//{null=null, 手表=220, Java=2, 书=2}
Map是双列集合的祖宗,它的功能是全部双列集合都可以继承过来使用的
方法名称 | 说明 |
public v put(K key,V value) | 添加元素 |
public int size() | 获取集合的大小 |
public void clear() | 清空集合 |
public boolean isEmpty() | 判断集合是否为空,为空返回true ,反之 |
public v get(Object key) | 根据键获取对应值(若无该键,返回null) |
public v remove(0bject key) | 根据键删除整个元素 |
public boolean containsKey(Object key) | 判断是否包含某个键 |
public boolean containsValue(0bject value) | 判断是否包含某个值 |
public Set |
获取全部键的集合 |
public collection |
获取map集合的全部值 |
补充:
public class ListTest1 {
public static void main(String[] args) {
Mapmap1=new HashMap<>();
map1.put("java1",10);
map1.put("java2",20);
Mapmap2=new HashMap<>();
map2.put("java3",10);
map2.put("java2",222);
map1.putAll(map2);//putAll:把map2集合的元素全部倒入一份到map1集合
System.out.println(map1);//{java3=10, java2=222, java1=10}
System.out.println(map2);//{java3=10, java2=222}
}
}
Map集合的遍历方式 | 说明 |
键找值 | 先获取Map集合全部的键,再通过遍历键来找值 |
键值对 | 把“键值对“看成一个整体进行遍历(难度较大) |
Lambda | JDK 1.8开始之后的新技术(非常的简单) |
方法名称 | 说明 |
public Set |
获取所有键的集合 |
public v get(0bject key) | 根据键获取其对应的值 |
Setkeys=map.keySet();
for (String key:keys) {
double value =map.get(key);
System.out.println(key+"====>"+value);
}
Map提供的方法 | 说明 |
Set |
获取所有“键值对”的集合 |
Set> entries=map.entrySet();
for (Map.Entryentry:entries) {
String key=entry.getKey();
double value=entry.getValue();
System.out.println(key+"====>"+value);
}
方法名称 | 说明 |
default void forEach(BiConsumer super K,? super v>action) | 结合lambda遍历Map集合 |
map.forEach((k,v)->{
System.out.println(k+"====>"+v);
});
HashMap(由键决定特点)︰无序、不重复、无索引;(用的最多)
HashMap跟Hashset的底层原理是一模一样的,都是基于哈希表实现的
实际上:原来学的Set系列集合的底层就是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据而已
HashMap的键依赖hashCode方法和equals方法保证键的唯一
如果键存储的是自定义类型的对象,可以通过重写hashCode和equals方法,这样可以保证多个对象内容一样时,HashMap集合就能认为是重复的
LinkedHashMap (由键决定的特点):有序,不重复,无索引
底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外的多了一个双链表的机制记录元素顺序(保证有序)
实际上:原来学习的LinkedHashSet集合的底层原理就是LinkedHashMap
TreeMap(有键决定特点):按照大小默认升序排序:不重复、无索引
原理:TreeMap跟TreeSet集合的底层原理是一样的,都是基于红黑树实现的排序
TreeMap集合同样也支持两种方式来指定排序规则
让类实现Comparable接口,重写比较规则
TreeMap集合有一个有参数构造器,支持创建Comparator比较器对象,以便用来指定比较规则
集合的嵌套:指集合中的元素又是一个集合
import java.util.*;
public class ListTest1 {
public static void main(String[] args) {
Map> map=new HashMap<>();
List cities1=new ArrayList<>();
Collections.addAll(cities1,"南京市","扬州市","苏州市","无锡市","常州市");
map.put("江苏省",cities1);
System.out.println(map);//{江苏省=[南京市, 扬州市, 苏州市, 无锡市, 常州市]}
}
}
也叫Stream流,是Jdk8开始新增的一套APl(java.util.stream.*),可以用于操作集合或者数组的数据
优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好
//List
List names=new ArrayList<>();
Collections.addAll(names,"张三丰","张无忌","周芷若","赵敏","张强");
List list=new ArrayList<>();
for (String name:names) {
if (name.startsWith("张")&&name.length()==3){
list.add(name);
}
}
//Stream流
List list2=names.stream().filter(s->s.startsWith("张")).filter(a->a.length()==3).collect(Collectors.toList());
public interface Stream
Collection提供的如下方法 | 说明 |
default Stream |
获取当前集合对象的Stream流 |
List names=new ArrayList<>();
Collections.addAll(names,"张三丰","张无忌","周芷若","赵敏","张强");
Stream stream=names.stream();
Arrays类提供的如下方法 | 说明 |
public static |
获取当前数组的stream流 |
Stream类提供的如下方法 | 说明 |
public static |
获取当前接收数据的Stream流 |
Set set=new HashSet<>();
Collections.addAll(set,"刘德华","张曼玉","蜘蛛精","马德","德玛西亚");
Stream stream1=set.stream();
stream1.filter(s->s.contains("德")).forEach(s-> System.out.println(s));
Map map=new HashMap<>();
Set keys=map.keySet();
Stream ks=keys.stream();
Collection values=map.values();
Stream vs=values.stream();
Set>entries=map.entrySet();
Stream> kvs=entries.stream();
kvs.filter(e->e.getKey().contains("巴")).forEach(e->System.out.println(e.getKey()+"---->"+e.getValue()));
String[]names2={"张三丰","张无忌","周芷若","赵敏","张强"};
Stream s1=Arrays.stream(names2);
Stream s2=Stream.of(names2);
中间方法指的是调用完成后会返回新的Stream流,可以继续使用(支持链式编程)
Stream提供的常用中间方法 | 说明 |
Stream |
用于对流中的数据进行过滤 |
Stream |
对元素进行升序排序 |
Stream |
按照指定规则排序 |
Stream |
获取前几个元素 |
Stream |
跳过前几个元素 |
Stream |
去除流中重复的元素 |
对元素进行加工,并返回对应的新流 | |
static |
合并a和b两个流为一个流 |
//数据
scores.stream().filter(s -> s >=60).sorted().forEach(s -> System.out.println(s));//升序
//对象
students.stream().filter(s -> s.getAge() >= 23 && s.getAge() <= 30).sorted((o1, o2)-> 02.getAge()- o1.getAge()).forEach(s -> System.out.println(s));//根据对象的年龄排序
//去身高最高的3位学生
students.stream().sorted((o1,o2) -> Double.compare(o2.getHeight(),o1.getHeight())).limit(3).forEach(s -> System.out.println(s));
students.stream().sorted((o1,o2) -> Double.compare(o2.getHeight(),o1.getHeight())).limit(3).forEach(System.out::println);
//身高最低的2名学生
students.stream().sorted((o1,o2) -> Double.compare(o2.getHeight(),o1.getHeight())).slip(students.size()-2).forEach(s -> System.out.println(s));
//找出身高超过168的学生叫什么名字,要求去除重复的名字
students.stream().filter(s -> s.getHeight() > 168).map(s->s.getName()).forEach(s -> system.out.println(s));
终结方法指的是调用完成后,不会返回新Stream了,没法继续使用流了
Stream提供的常用终结方法 | 说明 |
void forEach(consumer action) | 对此流运算后的元素执行遍历 |
long count() | 统计此流运算后的元素个数 |
Optional |
获取此流运算后的最大值元素 |
Optional |
获取此流运算后的最小值元素 |
//请计算出身高超过168的学生有几人
long size=students.stream().filter(s->s.getHeight()>168).count();
//请找出身高最高的学生对象,并输出
Student s=students.stream().max((o1, o2) -> Double.compare(o1.getHeight(),o2.getHeight() )).get();
//请找出身高最低的学生对象,并输出
Student s=students.stream().min((o1, o2) -> Double.compare(o1.getHeight(),o2.getHeight() )).get();
收集Stream流:就是把Stream流操作后的结果转回到集合或者数组中去返回
Stream流:方便操作集合/数组的手段;集合/数组:才是开发中的目的
流只能收集一次
Stream提供的常用终结方法 | 说明 |
R collect(collector collector) | 把流处理后的结果收集到一个指定的集合中去 |
object[] toArray() | 把流处理后的结果收集到一个数组中去 |
//请找出身高超过170的学生对象,并放到一个新集合中去返回
Liststudents1=students.stream().filter(a->a.getHeight()>170).collect(Collectors.toList());
Setstudents2=students.stream().filter(a->a.getHeight()>170).collect(Collectors.toSet());
//请找出身高超过170的学生对象,并把学生对象的名字和身高,存入到一个Map集合返回
Mapmap=students.stream().filter(a->a.getHeight()>170).distinct().collect(Collectors.toMap(a->a.getName(), a->a.getHeight()));
//distinct()去除重复对象
//请找出身高超过170的学生对象,并放到一个数组中去返回
Object[]arr=students.stream().filter(a->a.getHeight()>170).toArray();
Student[]arr=students.stream().filter(a->a.getHeight()>170).toArray(len->new Student[len]);
Collectors工具类提供了具体的收集方式 | 说明 |
public static |
把元素收集到List集合中 |
public static |
把元素收集到set集合中 |
public static collector toMap(Function keyMapper , Function valueMapper) | 把元素收集到Map集合中 |