前言

之前我们学习了使用数组来保存多个对象,但数组长度不可变化,如果需要保存数量变化的数据,数组就有点无能为力了,所以我们需要使用集合。

List 、Set、 Map
List:有序的集合,可以重复
Set:无序的集合,不可重复
Map: key-value

由图中可以看出,List和Set的父接口都是Collection

集合类和数组的不一样:
数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量);而集合里只能存放引用变量
集合重写了equals()和hashcode()方法:

方法:
测试Collection接口的常用方法:

//测试collection接口的常用方法
public class Demo1 {/*** 泛型是jdk5.0才出现的* Collection<String> coll=new ArrayList<String>();* jdk1.7之后* Collection<String> coll=new ArrayList<>();* @param args*/public static void main(String[] args) {//Collection<Integer> coll1=new ArrayList<>();//coll1.add(1); //自动封箱Collection<String> coll=new ArrayList<String>();//按顺序添加System.out.println(coll.isEmpty());  //truecoll.add("hello");coll.add("abc");coll.add("123");// boolean isEmpty(): 返回集合是否为空 当集合长度为0 时返回 true ,否则返回 falseboolean b=coll.isEmpty();System.out.println(b);   //false// int size(): 该方法返回集合里元素的个数。System.out.println(coll.size());// boolean contains(Object o): 返回集合里是否包含指定元素System.out.println(coll.contains("hello"));   //true// boolean remove(Object 0): 除集合中的指定元素。coll.remove("hello");System.out.println(coll.size());  //2coll.clear();System.out.println(coll.isEmpty());   //true}}

遍历集合元素的三种方式:

        Collection<String> coll=new ArrayList<String>();System.out.println(coll.isEmpty());  //truecoll.add("hello");coll.add("abc");coll.add("123");//第一种方法:增强for循环for(String str:coll) {System.out.println(str);}System.out.println("==========");//第二种方法:迭代器Iterator<String> it=coll.iterator();//当前容器中是否有元素while(it.hasNext()) {String str=it.next();System.out.println(str);}System.out.println("==========");//第三种:lambdacoll.forEach(a->System.out.println(a));

和集合相关的方法:

//和集合相关的方法public static void main(String[] args) {// TODO Auto-generated method stubCollection<String> c1=new ArrayList<>();c1.add("c");c1.add("c++");c1.add("java");Collection<String> c2=new ArrayList<>();c2.add("jsp");c2.add("php");c2.add("java");//可以添加进去,因为List有序// boolean containsAll(Collection c):集合里是否包含集合c里的所有元素。boolean b=c1.containsAll(c2);System.out.println(b);// boolean addAll(Collection c) 该方法把集合c 里的所有元素添加到指定集合里。boolean b2=c1.addAll(c2);c1.forEach(str->System.out.println(str));//c1.removeAll(c2);c1.forEach(str->System.out.println(str));}

List
默认初始容量:10

ArrayList底层的实现是线性表,实际是数组:

transient关键字修饰的变量不会被序列化。

下面程序示范了 List 集合的常规用法。

        List<String> list=new ArrayList<>();list.add("hello");list.add(0,"abc");list.forEach(str->System.out.println(str));list.set(1, "111");list.forEach(str->System.out.println(str));list.remove(0);list.forEach(str->System.out.println(str));System.out.println("============");//遍历for(int i=0;i<list.size();i++) {System.out.println(list.get(i));}

集合和数组的相互转换及排序

//集合转成数组public static void test1() {List<String> list=new ArrayList<>();list.add("hello");list.add(0,"abc");List<Integer> list2=new ArrayList<>();list2.add(1);list2.add(2);Object[] obj=list2.toArray();int sum=0;for(Object object:obj) {sum+=(Integer)object;}//经常用的方法Integer[] li=list2.toArray(new Integer[list2.size()]);for(Integer i:li) {sum+=i;}//对数组排序//默认升序Arrays.sort(li);System.out.println(Arrays.toString(li));String[] strs=new String[list.size()];Arrays.sort(list.toArray(strs));System.out.println(Arrays.toString(strs));    }static Comparator<String> com=new Comparator<String>() {public int compare(String o1, String o2) {return o1.length()-o2.length();}    };//数组转成集合  asList()//给集合排序,使用的是     Collections的sort方法  //底层还是Arrays.sort()public static void test2() {String[] str= {"hello","abc","bde"};//数组转成集合List<String> list=Arrays.asList(str);//集合的排序Collections.sort(list);  //底层还是Arrays.sort()System.out.println(list);//自定义排序规则:按长度排序//Collections.sort(list,com);//匿名表达式的形式Collections.sort(list,(o1,o2)->o1.length()-o2.length());System.out.println(list);}

练习:按照学生成绩排序
1.定义Student类
两个变量:name,score
方法:
2.定义集合,3个student对象,添加到集合
3.使用sort方法排序,排序是指定排序规则
4.输出排序后的集合

//方法一:
public class Student {private String name;private int score;public Student(){}public Student(String name, int score) {super();this.name = name;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic String toString() {return "Student [name=" + name + ", score=" + score + "]";}}
//方法二:
public class Student2 implements Comparable<Student2>{private String name;private int score;public Student2(){}public Student2(String name, int score) {super();this.name = name;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic String toString() {return "Student [name=" + name + ", score=" + score + "]";}@Overridepublic int compareTo(Student2 o) {return this.score-o.score;}}List<Student> stuList = new ArrayList<>();stuList.add(new Student("admin",60));stuList.add(new Student("zhangsan",90));stuList.add(new Student("lisi",80));Collections.sort(stuList,(stu1,stu2)->stu1.getScore()-stu2.getScore());System.out.println(stuList);System.out.println("===========================");List<Student2> stuList2 = new ArrayList<>();stuList2.add(new Student2("admin",60));stuList2.add(new Student2("zhangsan",90));stuList2.add(new Student2("lisi",80));Collections.sort(stuList2);System.out.println(stuList2);

练习
实现ArrayList

//MyArray      (String)
class MyArray{//int size;//表示集合的元素个数//String[] strArray;private int size;private String[] strArray;//1.定义无参的构造方法  默认给数组10个public MyArray(){strArray = new String[10];}//2.定义一个带参的构造方法public MyArray(int length){strArray = new String[length];}/*3.add(String str);判断元素的个数和数组的长度之间的关系  size>=strArray 扩容添加元素size++;*/public void add(String str){if(size>=strArray.length){grow();}strArray[size]=str;size++;}/*4.定义grow方法规则:数组长度的一半(如果数组长度为1 ,扩容应该是+1)*/private void grow(){if(strArray.length<=1){strArray = Arrays.copyOf(strArray, strArray.length+1);}else{strArray = Arrays.copyOf(strArray, strArray.length+strArray.length/2);}}/*5.add(int index,String str)判断元素的个数和数组的长度之间的关系  size>=strArray 扩容当前的数组元素后移插入元素size++;*/public void add(int index,String str){if(size>strArray.length){grow();}//{1,2,3}  index = 1      3 -  1//{1,1,2,3}System.arraycopy(strArray, index, strArray, index+1, size-index);strArray[index] = str; size++;}/*6.remove(int index)当前的数组元素前移size--;*/public void remove(int index){//{1,2,3}  index = 1     3    1-1  //{1,3} System.arraycopy(strArray, index+1, strArray, index, size-index-1);strArray[--size]=null;}//7.set(int index,String str):修改public void set(int index,String str){strArray[index] = str;}/*8.get(int index):获取元素*/public String get(int index){return strArray[index];}     /*9.size():返回集合中的元素个数*/public int size(){return size;}
}public class Demo {public static void main(String[] args) {MyArray arr = new MyArray();arr.add("hello");arr.add("abc");arr.add("admin");arr.remove(1);arr.set(1, "admin1111");arr.add(1,"222");for(int i = 0;i<arr.size();i++){System.out.println(arr.get(i));}}
}

泛型

什么是泛型?
java泛型设计原则:编译不出错,运行时不会出现ClassCastException


泛型基础

1.泛型类:

在类上定义的泛型,在方法中也可以使用
class TestObj<T>{private T obj;private int age;private String name;
......}

测试代码:(通过泛型定义变量的类型,比如老师工资和学生学号)

public class TestObj<T> {private T data;private String name;public TestObj() {}public TestObj(T data, String name) {super();this.data = data;this.name = name;}public T getData() {return data;}public void setData(T data) {this.data = data;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "TestObj [data=" + data + ", name=" + name + "]";}}TestObj<String> stu=new TestObj<>();stu.setName("张三");stu.setData("201716122387");System.out.println(stu);TestObj<Float> emp=new TestObj<>();emp.setData(10000.231f);emp.setName("老师");System.out.println(emp);

结果:

TestObj [data=201716122387, name=张三]
TestObj [data=10000.231, name=老师]


2.泛型方法

   <T> void f(){}

方法返回类型前面有<>才是泛型方法
泛型方法所在的类不一定是泛型类

//输出任意数据类型的数组元素public static <T> void showData(T[] arr) {for(T t:arr) {System.out.println(t);}}public static void test3() {Integer[] num= {1,2,3};//必须是引用类型showData(num);}

结果:

1
2
3

3.泛型类派生出的子类:

  • 子类明确泛型类的类型参数变量,该子类就是一个普通类

  • 子类不明确泛型类的类型参数变量,该子类是一个泛型类

以接口为例:泛型接口

泛型接口:

   interface Demo<T>{}
interface Inter<T>{void show(T t);
}
class Im implements Inter<String>{@Overridepublic void show(String t) {System.out.println(t);}
}
class Im2<T> implements Inter<T>{@Overridepublic void show(T t) {System.out.println(t);        }
}
使用规则:
public class Demo3 {public static void main(String[] args) {Inter<String> i2= new Im();i2.show("hello");Inter<Integer> i3= new Im2<>();i3.show(1);}
}

4.泛型的使用-通配符 ? 表示任意数据类型

 public static void show(List<Object> list){for(Object obj : list){System.out.println(obj);}}
    List<Object>   和  List<String>不存在继承关系

5.设置通配符的上限List<? extends Animal> list
6.设置通配符的下限List<? super Number> list

public class Demo4 {public static void show(List<?> list){for(Object obj : list){System.out.println(obj);}}public static void test1(List<? extends Number> list){for(Number obj : list){System.out.println(obj);}}public static void test2(List<? super Number> list){for(Object obj : list){System.out.println(obj);}}public static void main(String[] args) {List<Object> list = new ArrayList<>();//List<Integer> list = new ArrayList<>();list.add(1);list.add(2);test2(list);/*List<String> list = new ArrayList<>();list.add("abc");list.add("hello");list.add("123");show(list);*/}}

通配符的错误使用:

class A<?>{}
public <?> void t(List<?> list){}
List<?> list = new ArrayList<?>(); //错在ArrayList<?>()


Stream

Stream:和io没有任何关系

流式思想:像生产流水线一样,一个操作接一个操作。

使用流操作集合更高效

2.stream的特性
1.stream不存储数据
2.stream不改变源数据
3.stream的延迟执行特性

3.使用Stream流的步骤:数据源→转换成流→操作1→操作2→……

4.数据源(source):可以是集合、数组等。

5.获取流:

 // Listlist.stream();// 数组Stream.of();

6.常用方法
Stream只能被使用一次,如果还想使用,必须重新获取流。
如果不重新获取,会得到异常:stream has already been operated upon or closed

1.filter 方法用于通过设置的条件过滤出元素2.map 方法用于映射每个元素到对应的结果3.limit 方法用于获取指定数量的流4.跳过前n个stream.skip5.流的连接Stream.concat(stream1,stream2)6.回数量count7.可以把流转换为 List 集合类型:collect(Collectors.toList());8.求和的方法reduce(0, (x, y) -> x + y)9.去重distinct()10.排序:sorted()

返回的是流,就可以用foreach()

public class Demo5 {public static void test2() {Stream<Integer> stream=Stream.of(1,2,3,4,5,6,7);Stream<Integer> numStream=stream.filter(e->e%2!=0);//有延迟//返回的是流,就可以用foreachnumStream.forEach(e->{System.out.println("=======");System.out.println(e);});System.out.println("filter");stream=Stream.of(1,2,3,4);stream.map(e->e*e).forEach(e->System.out.println(e));stream.limit(3).forEach(e->System.out.println(e));System.out.println("=======");//跳过stream.skip(3).forEach(e->System.out.println(e));}public static void test() {List<String> listStr=new ArrayList<>();listStr.add("hi");listStr.add("heelo");Integer[] num= {1,2,3,4};Stream<String> s=listStr.stream();Stream<Integer> i=Stream.of(num);Stream.concat(s, i).forEach(e->System.out.println(e));//报异常stream has already been operated upon or closedi.forEach(e->System.out.println(e));i.forEach(e->System.out.println(e));  }public static void test3() {Stream<Integer> stream=Stream.of(1,2,3,4,5,6,7);System.out.println(stream.count());List<Integer> i=stream.collect(Collectors.toList());System.out.println(i);//0相当于sum初始值System.out.println(stream.reduce(0,(x,y)->x+y));stream=Stream.of(1,2,1,3);stream.distinct().forEach(e->System.out.println(e));stream=Stream.of(2,5,3);stream.sorted().forEach(e->System.out.println(e));//从大到小排stream.sorted((x,y)->y-x).forEach(e->System.out.println(e));}
}

练习
1.有如下整数1,-2,-3,4,-5,使用Stream取元素绝对值并打印

 stream.map(e->Math.abs(e)).forEach(System.out::print);

2.给定一个数字列表,如何返回一个由每个数的平方构成的列表
给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】。

stream.map(e-> e*e).forEach(System.out::print);

3.有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,
使用Stream将以郭字开头的元素存入新集合

stream.filter(e->e.starWith("郭")).colect(Colectors.toList());

4.已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、
武眠风、冯默风、罗玉风},

使用Stream
1、取出前2个元素并在控制台打印输出。

stream.limit(3).forEach(System.out::print);

2、取出后2个元素并在控制台打印输出。

stream.skip(list.size()-2).forEach(System.out::print);

5.怎样用 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)
);

stream.map(e->1).reduce(0,(x,y)->x+y)

6.找出2011年发生的所有交易, 并按交易额排序(从低到高)

class Transaction {   private int year;   //交易时间private int value;  //交易额方法。。。。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));stream.filter(e->e.getYear()==2011).sorted((t1,t2)->t1.getValue()-t2.getValue()).forEach(....);

集合

List集合的实现类

LinkedListArrayList都是线程不安全的
Vector是线程安全的

List<String> list = new LinkedList<>();
List<String> v = new Vector<>();

练习

class LinkList{private int size = 0; // 节点个数private Node first; // 第一个节点private Node last; // 最后一个节点//无参构造方法public LinkList() {}//添加元素public void add(String str) {Node node=new Node(null,str,null);if(size==0) {this.first=node;this.last=node;}else {this.last.next=node;node.prev=this.last;this.last=node;}size++;}//插入//插入时先写最后插入public void add(int index, String str) {//最后,this.add()if(index == size){this.add(str);return;}Node node = new Node(null,str,null);if(index==0){//在最前边node.next = this.first;this.first.prev = node;this.first = node;}else{Node node1 = this.getNode(index);node1.prev.next = node;node.prev = node1.prev;node.next = node1;node1.prev = node;}size++;}// 获取指定位置的节点Node getNode(int index) {Node node=this.first;for(int i=0;i<index;i++) {node=node.next;}return node;}//删除public void remove(int index) {if(index == 0){this.first.next.prev = null;this.first = this.first.next;}else if(index == size-1){this.last.prev.next = null;this.last = this.last.prev;}else{Node node = this.getNode(index);node.prev.next = node.next;node.next.prev = node.prev;}size--;}//返回节点的内容public String get(int index){return this.getNode(index).data;}// 返回元素个数public int size(){return size;}//利用节点存储数据private class Node {Node prev; // 上一个节点String data; // 元素Node next; // 下一个节点public Node(Node prev, String data, Node next) {super();this.prev = prev;this.data = data;this.next = next;}}}
public class DemoLinkedList {public static void main(String[] args) {LinkList linkList=new LinkList();linkList.add(0,"hello");System.out.println(linkList.size());linkList.add(1,"success");linkList.add(2,"su");System.out.println(linkList.get(0));System.out.println(linkList.get(1));System.out.println(linkList.get(2));linkList.remove(2);System.out.println(linkList.get(0));System.out.println(linkList.get(1));}}

运行结果:

1
hello
success
su
hello
success

Set集合
不重复:先判断hashCode(); 相同,还要判断equals()方法,如果返回true表示一个对象,否则是不同对象

HashSet和TreeSet
HashSet基于HashMap的实现
HashSet的元素是map中的key,value值对应的是一个常量

HashSet:


public class Demo7 {public static void test(){Set<String> set = new HashSet<>();set.add("张三");set.add("张三");set.add("李四");set.add("王五");set.remove("王五");set.forEach(System.out::println);}public static void test2(){Set<Emp> set = new HashSet<>();set.add(new Emp("张三"));set.add(new Emp("张三"));set.add(new Emp("李四"));set.add(new Emp("王五"));set.forEach(System.out::println);  //Emp [name=张三]//Emp [name=李四]//Emp [name=王五]}public static void main(String[] args) {test2();}}
public class Emp {private String id;private String name;public Emp(){}public Emp(String name){this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((id == null) ? 0 : id.hashCode());result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Emp other = (Emp) obj;if (id == null) {if (other.id != null)return false;} else if (!id.equals(other.id))return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}@Overridepublic String toString() {return "Emp [name=" + name + "]";}}

TreeSet的元素必须是有排序规则的对象,否则会运行时异常

public static void test(){TreeSet<String> set = new TreeSet<>();set.add("abc");set.add("bed");set.add("avs");set.forEach(System.out::println);}public static void test2(){TreeSet<Emp> set = new TreeSet<>((emp1,emp2)->emp1.getName().length()-emp2.getName().length());set.add(new Emp("admin"));set.add(new Emp("baf"));set.add(new Emp("abmin333"));set.forEach(System.out::println);}

Map集合

疯狂java——集合、泛型、Stream相关推荐

  1. 002 Java集合泛型面试题

    Java集合/泛型面试题 1 ArrayList和linkedList的区别 ArrayList: 可以看作是能够自动增长容量的数组 ArrayList底层的实现是Array, 数组扩容实现 Arra ...

  2. 疯狂Java讲义-泛型

    泛型 本章思维导图 泛型入门 Java集合有个缺点--把一个对象"丢进"集合里之后,集合就会"忘记"这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变 ...

  3. Java集合泛型作为参数时,使用中的一些问题。包括但不限于PECS原则

    目录 泛型中的PECS原则以及使用注意 一.泛型中的型变(协变.逆变.不可变) 1. 什么是型变 2. 什么是协变(Covariance) 3. 什么是逆变(Contravariance) 4. 不可 ...

  4. JAVA集合泛型,类型擦除,类型通配符上限之类的知识点

    感觉定义要比PYTHON严谨很多,一切源于静态语言的特点吧.. 于是语法上就复杂很多,值不值得呢? 参考测试URL: http://www.cnblogs.com/lwbqqyumidi/p/3837 ...

  5. Java面试题汇总2021最新(集合泛型含答案下载)

    Java面试题及答案2021最新24题(集合&泛型) 最近给大家整理了一批Java面试题一共24题,主要是搜集的Java集合&泛型这块的,是20201最新时间整理的,并且都含答案打包下 ...

  6. Java中快速处理集合_简洁又快速地处理集合——Java8 Stream(上)

    作者:Howie_Y,系原创投稿 主页:www.jianshu.com/u/79638e5f0743 Java 8 发布至今也已经好几年过去,如今 Java 也已经向 11 迈去,但是 Java 8 ...

  7. 李刚疯狂java讲义第3_【Java】-NO.16.EBook.4.Java.1.009-【疯狂Java讲义第3版 李刚】- 泛型...

    1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.009-[疯狂Java讲义第3版 李刚]- 泛型 Style:EBook Series:Java Si ...

  8. Java SE基础知识详解第[13]期—不可变集合、Stream流、异常

    写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...

  9. Java笔记_16(不可变集合、Stream流、方法引用)

    Java笔记_16 一.创建不可变集合 1.1.创建不可变集合的应用场景 1.2.创建不可变集合的书写格式 二.Stream流 2.1.体验Stream流 2.2.Stream流的思想和获取Strea ...

最新文章

  1. 关于STRUCT优化的一个点
  2. ado数据处理超时限制
  3. LInux 下文件包的使用
  4. JSPServlet精华笔记
  5. c中获取python控制台输出_linux c程序中获取shell脚本输出的实现方法
  6. 12款很酷的使用大头照的国外名片设计作品
  7. 关于 react的生命周期
  8. Java——can U do
  9. 大数据导论章节答案_大数据概论智慧树章节答案
  10. python图像风格迁移_Python 超简单实现9种图像风格迁移
  11. 解决spring-data-jpa 级联添加时,主表放弃对外键维护时外键字段为null
  12. vue 自动播放语音
  13. 使用IPV6技术访问网站
  14. 搜索引擎和知识图谱那些事
  15. 2012年春节放假通知
  16. 听dalao讲课8.4
  17. android 屏幕统计,OffScreen - 屏幕时间统计
  18. 大数据 MapReduce使用
  19. 刷爆网络的动态条形图,3行Python代码就能搞定
  20. 心血来潮:重新温习一下C语言的指针

热门文章

  1. WebRTC实时通信系列教程8 打通P2P连接和信令通信
  2. win7系统突然变慢的解决方法
  3. Word2Vec--词向量模型
  4. cbnertvirtual内部框架下载_快速开发,支持前后端分离,微服务框架
  5. 简单记录下几家公司的面试经历(Java一年经验)
  6. 男人的快乐不就来了?
  7. 关于卷积神经网络细节的深入理解
  8. Linux系统:我们的征途是星辰大海!
  9. maven中hibernate-core和struts2-core中javassist解决办法(cannot be cast to javassist.util.proxy.Proxy)
  10. 什么是url静态化?