1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > JAVA最常用容器 API(全是干货 刷题必备高效工具!)

JAVA最常用容器 API(全是干货 刷题必备高效工具!)

时间:2020-04-11 04:54:44

相关推荐

JAVA最常用容器 API(全是干货 刷题必备高效工具!)

包含众多资源,都是自己两年间自己总结的,都是非常非常常用的。有各大容器、以及配套工具类的讲解,还有常用API,以及JAVA8中的Lambda、函数式接口,全文很长,全是干货,刷题必备!请参看目录阅读!(此版本非最终版,有很多缺漏和排版问题)

目录

一、数据结构容器1.String补充:字符串池 2.StringBuilder与StringBuffer2.ArrayList3.集合1、单列集合java.util.Collection1.1 List接口1.1.1ArraryList1.1.2LInkedList 1.2Set接口1.2.1HashSet1.2.2LinedHashset1.2.3集合的交并补 1.3Queue 2、双列集合java.util.Map 二、一些常用APIArrays类Collections类Math类Object类1、toString 方法2、equals方法3、hashcode&equalsObjects类 System类1、currentTimeMillis方法2、arraycopy方法 Scanner类1、next2、nextLine3、hasNext 日期相关类1 Date类2 DateFormat类**构造方法****格式规则**常用方法实质: 3 Calendar类概念获取方式常用方法 BigInteger类 三、迭代器四、C++与JAVA对比**1、JAVA迭代器与C++迭代器****2、数据结构定义方法**3、长度 五、可变参数六、Lambda省略规则 七、函数式接口1 Supplier < T >接口2 Consumer< T >接口3 Predicate< T >接口4 Function

此外

推荐菜鸟教程这里讲得容器也很好推荐大家看一下。图片部分还没有整理,所以现在都看不到,但是无伤大雅,有需要pdf版本的联系我。更多资源(算法数据结构尽请期待)

一、数据结构容器

1.String

介绍:

1、构造方法

public String() public String(char[] cs)public String(byte[] bs)//byte bytes[]={97,98,99};//String str=new String(bytes) 会新建一个 "abc"

2、常用方法

比较

public boolean euqals(Object obj)public boolean equalsIgnoreCase(String obj)public int compareTo(String str)//两字符串完全相同返回0; 当前字符串小于参数字符串返回负数;大于返回正数public int compareToignoreCases(String str)//而用==号 对于引用数据类型判断的是两侧是否指向同一个对象

基本功能

//获取长度public int length() //将参数字符串连接到本字符串的末尾public String concat(String str)//获取某一个charpublic char charAt(int index) //注意不能像C++那样 数组下标访问 注意是从0开始//找参数字符串第一次出现的位置public int indexOf(String str)//可把参数类型String 改成int 查找某个字符 ,而且可以lastIndexOf 找最大的下标,也即从后往前找public int indexOf(String str,int fromIndex)//截取得到子串public String substring(int beginIndex)//从beginIndex到结尾public String substring(int beginIndex,int endIndex)//注意是[beginIndex,endIndex)//判空public boolean isEmpty()

转化(String -> others)

//将此字符串转换为新的字符数组public char[] toCharArray () //String->CharArray->String 这个应该很有用!!!//使用平台的默认字符集将该 String编码转换为新的字节数组public byte[] getBytes ()还可以用各个包装类的静态方法如:Boolean.parseBoolean(String str) Integer.parseInt(String str) 经过一些实验对于任何非"true"字符串,parseBoolean总是false,对于非数字字符串,parseInteger会报错

转化(others->String)

1、数组 加 构造方法2、一般方法是 直接 str+""就行了3、还可以调用String的静态方法 valueof()String str=String.valueOf(100)

替换

//替换public String replace (CharSequence target, CharSequence replacement) //例子:String str = "itcast itheima";String replace = str.replace("it", "IT");System.out.println(replace); // ITcast ITheima

拆分

//将此字符串按照给定的regex(规则)拆分为字符串数组public String[] split(String regex)//例子:String s = "aa|bb|cc";String[] strArray = s.split("|"); // ["aa","bb","cc"]

关于split 的转义字符 以下参考 CSDN

在Java中,不管是String.split(),还是正则表达式,有一些特殊字符需要转义,

这些字符是

( [ { / ^ - $ ¦ } ] ) ? | * + .

转义方法为字符前面加上"\",这样在split、replaceAll时就不会报错了;

不过要注意,String.contains()方法不需要转义。

所以正常的写法是这样的:

1、如果用“.”作为分隔的话,必须是如下写法:String.split("\."),这样才能正确的分隔开,不能用String.split(".");

2、如果用“|”作为分隔的话,必须是如下写法:String.split("\|"),这样才能正确的分隔开,不能用String.split("|");

“.”和“|”都是转义字符,必须得加"\";

3、如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“a=1 and b =2 or c=3”,把三个都分隔出来,可以用String.split(“and|or”);

split分隔符总结

1.字符"|","*","+“都得加上转义字符,前面加上”\"。

2.而如果是" \ “,那么就得写成”\\"。

3.如果一个字符串中有多个分隔符,可以用"|"作为连字符。

大小写

public String toLowerCase()public String toUpperCase()

去掉首尾空白符

public String trim()

补充:字符串池

程序当中直接写上的双引号字符串,就在字符串常量池中用+ 得到的

new出来的不在

2.StringBuilder与StringBuffer

菜鸟教程参考

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

可变字符序列

StringBuilder是个字符串的缓冲区,即它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进 行各种操作。

构造方法:

public StringBuilder()public StringBuilder(String str) // String -> StringBuilder

常用方法:

public StringBuilder append(...)

例如:

StringBuilder builder= new StringBuilder();StringBuilder bulider2=builder.append("Hello");builder.append(100).append(false);builder.append(true);

用toString方法把StringBuilder转化成String//StringBuilder -> String

2.ArrayList

介绍:

1、定义

ArrayList<String> list=new ArrayList<String>(); // 也可省略后一个<>里的String

2、成员方法

//public boolean add(E e)list.add("AAA");arraylist.add(int index,E element)//如果 index 没有传入实际参数,元素将追加至数组的最末尾。//public E remove(int index) 返回被删除的元素 (下标从0开始) list.remove(0);//public E get(int index) 返回指定元素list.get(int index)//public int size()list.size();

注意:

ArrayList对象不能存储基本类型,只能存储引用类型的数据。类似 < int > 不能写,但是存储基本数据类型对应的 包装类型是可以的。所以,想要存储基本类型数据, <> 中的数据类型,必须转换后才能编写可以直接sout 变量名 回输出这种形式的[AAA,BBB,CCC] toString方法已经重写不必重写equals方法和hashcode

3.集合

心得:当容器元素唯一、不重复时,需要重写 存储元素类的equals方法和hashcode方法

TreeSet 是有序的去重集合,TreeMap 是 key 有序的哈希表,它们也是基于红黑树实现的。

1、单列集合java.util.Collection

Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是 java.util.List 和 java.util.Set 。

其中,

List 的特点是元素有序、元素可重复。

Set 的特点是元素无 序,而且不可重复。

List 接口的主要实现类有 java.util.ArrayList 和 java.util.LinkedList ,

Set 接口 的主要实现类有 java.util.HashSet 和 java.util.TreeSet 。

下面方法可 用于操作所有的单列集合。方法如下:

public boolean add(E e) : 把给定的对象添加到当前集合中 public void clear() :清空集合中所有的元素public boolean remove(E e) : 把给定的对象在当前集合中删除public boolean contains(E e) : 判断当前集合中是否包含给定的对象public boolean isEmpty() : 判断当前集合是否为空public int size() : 返回集合中元素的个数public Object[] toArray() : 把集合中的元素,存储到数组中。//Collection -> Array 调用toArray//Array -> Collection 只能遍历

1.1 List接口

List接口特点:

它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、 22、33的顺序完成的)。它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素

ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

公有方法:

public E get(int index) :返回集合中指定位置的元素。 public E set(int index, E element) :用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

1.1.1ArraryList

不多说了,在前边

1.1.2LInkedList

LinkedList集合也可以作为堆栈,

特有方法:

public void addFirst(E e) :将指定元素插入此列表的开头。public void addLast(E e) :将指定元素添加到此列表的结尾。 public E removeFirst() :移除并返回此列表的第一个元素。 public E removeLast() :移除并返回此列表的后一个元素。 public E getFirst() :返回此列表的第一个元素。 public E getLast() :返回此列表的后一个元素。 public E pop() :从此列表所表示的堆栈处弹出一个元素。public void push(E e) :将元素推入此列表所表示的堆栈。 public boolean isEmpty() :如果列表不包含元素,则返回true

1.2Set接口
1.2.1HashSet

它所存储的元素是不可重复的,并且元素都是无序的

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保 证HashSet集合中的对象唯一

1.2.2LinedHashset

元素不可重复,但是有序

1.2.3集合的交并补

参考

Set<String> set1 = new HashSet<>();Set<String> set2 = new HashSet<>();set1.add("a");set1.add("b");set1.add("c");set2.add("c");set2.add("d");set2.add("e");//交集set1.retainAll(set2);System.out.println("交集是 "+set1);

1.3Queue

Queue接口的一些方法

//尾部进队boolean add(E e); //@throws IllegalStateException if the element cannot be added at thistime due to capacity restrictionsboolean offer(E e);//@return {@code true} if the element was added to this queue, else{@code false}//头部出队E remove();// @return the head of this queue //@throws NoSuchElementException if this queue is emptyE poll();//@return the head of this queue, or {@code null} if this queue is empty//查看队头元素E element();//@return the head of this queue @throws NoSuchElementException if this queue is emptyE peek();//@return the head of this queue, or {@code null} if this queue is empty

offer、poll、peek面对满队、空队、空队的情况下不会抛出异常。

offer,add 区别:

一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。

这时新的 offer 方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。

poll,remove 区别:

remove() 和 poll() 方法都是从队列中删除第一个元素。remove() 的行为与 Collection 接口的版本相似, 但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。

peek,element区别:

element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null。

目前看来java提供了很多实现了阻塞接口的Queue,还有一些没实现的

就我而言

**想要用一般队列就用LinkedList ****优先队列就用PriorityQueue,**注意要实现Comparable接口,重写对象里的CompareTo,栈就用Stack

更多请参考

LinkedList<String> ll = new LinkedList<String>(); ll.push("wangchen");ll.push("lisi");ll.push("xiaohong");for(int i=0;i<ll.size();i++) {System.out.println("第"+i+"个: "+ll.get(i));}System.out.println("顶端:"+ll.peek()+"\n\n\n\n\n");Stack<String> s = new Stack<String>();s.push("wangchen");s.push("lisi");s.push("xiaohong");for(int i=0 ; i<s.size() ; i++)System.out.println("第"+i+"个:"+s.get(i));System.out.println("顶端:"+s.peek());第0个: xiaohong第1个: lisi第2个: wangchen顶端:xiaohong第0个:wangchen第1个:lisi第2个:xiaohong顶端:xiaohongLinkedList<String> ll = new LinkedList<String>();ll.offer("111");//进队ll.offer("222");ll.offer("333");System.out.println(ll.peek());//队头ll.poll();//出队System.out.println(ll.peek());//队头

优先队列

package lanqiao.practice;class Studentt implements Comparable<Studentt>{private int id;private String name;@Overridepublic int compareTo(Studentt o) {//id降序return o.id-this.id;}}public class demo02_queue {public static void main(String[] args) {PriorityQueue<Studentt> pq = newPriorityQueue<Studentt> ();Studentt s2 = new Studentt(2, "lisi");Studentt s1 = new Studentt(1, "wangchen");Studentt s4 = new Studentt(4, "xiaohong");Studentt s3 = new Studentt(3, "zhangsan");pq.offer(s1);pq.offer(s2);pq.offer(s3);pq.offer(s4);//无论怎样更改入队顺序,最终结果不变System.out.println(pq.size());while(pq.peek()!=null) {System.out.println(pq.poll());}}//main}Studentt [id=4, name=xiaohong]Studentt [id=3, name=zhangsan]Studentt [id=2, name=lisi]Studentt [id=1, name=wangchen]

2、双列集合java.util.Map

key键 -value值

Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。

HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键KEY的hashCode()方法、equals()方法。LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

LinkedHashMap 保存了记录的插入顺序,在用 Iterator 遍历时,先取到的记录肯定是先插入的;遍历比 HashMap 慢;

TreeMap 实现 SortMap 接口,能够把它保存的记录根据键排序(默认按键值升序排序,也可以指定排序的比较器)

一般情况下,使用最多的是 HashMap。HashMap:在 Map 中插入、删除和定位元素时;TreeMap:在需要按自然顺序或自定义顺序遍历键的情况下; LinkedHashMap:在需要输出的顺序和输入的顺序相同的情况下。

Map接口中定义了很多方法,常用的如下:

public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。

public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。

public V get(Object key)根据指定的键,在Map集合中获取对应的值。

getOrDefault(Object key, V defaultValue)

map中有该key就返回key对应的value,没有该key,就返回defaultValue

比如:在统计单词出现的次数时,可以这样map.put( str[i] , map.getOrDefault(str[i],0) + 1 );//单词出现过就 直接获得value+1,没出现则是0+1

boolean containsKey(Object key)判断集合中是否包含指定的键。

public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。

public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。

public Set<V> values()获取值集合

tips:

使用put方法时

若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中;若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。

Map集合遍历键找值方式

代码演示:

public class MapDemo01 {public static void main(String[] args) {HashMap<String, String> map = new HashMap<String,String>();map.put("胡歌", "霍建华");map.put("郭德纲", "于谦");map.put("薛之谦", "大张伟");Set<String> keys = map.keySet();for (String key : keys) {String value = map.get(key);System.out.println(key+"的CP是:"+value);} }}

Map集合遍历键值对方式

public class MapDemo02 {public static void main(String[] args) {HashMap<String, String> map = new HashMap<String,String>();map.put("胡歌", "霍建华");map.put("郭德纲", "于谦");map.put("薛之谦", "大张伟");// 获取 所有的 entry对象 entrySetSet<Map.Entry<String,String>> entrySet = map.entrySet();for (Map.Entry<String, String> entry : entrySet) {String key = entry.getKey();String value = entry.getValue(); System.out.println(key+"的CP是:"+value);}}}

**练习:**每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。

注意,学生姓名相同并且年龄相同视为同一名学生。

编写学生类:

public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}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;}@Overridepublic boolean equals(Object o) {if (this == o)return true;if (o == null || getClass() != o.getClass())return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}}

编写测试类:

public class HashMapTest {public static void main(String[] args) {//1,创建Hashmap集合对象。Map<Student,String>map = new HashMap<Student,String>();//2,添加元素。map.put(newStudent("lisi",28), "上海");map.put(newStudent("wangwu",22), "北京");map.put(newStudent("zhaoliu",24), "成都");map.put(newStudent("zhouqi",25), "广州");map.put(newStudent("wangwu",22), "南京");//3,取出元素。键找值方式Set<Student>keySet = map.keySet();for(Student key: keySet){Stringvalue = map.get(key);System.out.println(key.toString()+"....."+value);}}}

注意!!

当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法(如果忘记,请回顾HashSet存放自定义对象)。如果要保证map中存放的key和取出的顺序一致,可以使用java.util.LinkedHashMap集合来存放。

LinkedHashMap例子

我们知道HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办呢?

在HashMap下面有一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构。

public class LinkedHashMapDemo {public static void main(String[] args) {LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();map.put("邓超", "孙俪");map.put("李晨", "范冰冰");map.put("刘德华", "朱丽倩");Set<Map.Entry<String, String>> entrySet = map.entrySet();for (Map.Entry<String, String> entry : entrySet) {System.out.println(entry.getKey() + " " + entry.getValue());}}}邓超 孙俪李晨 范冰冰刘德华 朱丽倩

又一个例子:

需求:

计算一个字符串中每个字符出现次数。

分析:

获取一个字符串对象创建一个Map集合,键代表字符,值代表次数。遍历字符串得到每个字符。判断Map中是否有该键。如果没有,第一次出现,存储次数为1;如果有,则说明已经出现过,获取到对应的值进行++,再次存储。打印最终结果

代码:

public class MapTest {public static void main(String[] args) {//友情提示System.out.println("请录入一个字符串:");String line = new Scanner(System.in).nextLine();// 定义 每个字符出现次数的方法findChar(line);}private static void findChar(String line) {//1:创建一个集合 存储 字符 以及其出现的次数HashMap<Character, Integer> map = new HashMap<Character, Integer>();//2:遍历字符串for (int i = 0; i < line.length(); i++) {char c = line.charAt(i);//判断 该字符 是否在键集中if (!map.containsKey(c)) {//说明这个字符没有出现过//那就是第一次map.put(c, 1);} else {//先获取之前的次数Integer count = map.get(c);//count++;//再次存入 更新map.put(c, ++count);}}System.out.println(map);}}

​ 对key 和 value排序

HashMap<String,Integer> hashMap = new HashMap<String,Integer>();hashMap.put("wangchen",98);hashMap.put( "xia",96);hashMap.put( "ta",85);hashMap.put( "hu",77);Set<String> keySet = hashMap.keySet();for (String string : keySet) {System.out.println(string + " : " + hashMap.get(string));}//对key定义排序规则,也即按照名字的首字母排序//map.keyset-> array或者ArrayList 再排序System.out.println("\n名字升序:");Object[] array = keySet.toArray();Arrays.sort(array);for (Object object : array) {System.out.println(object + " : " + hashMap.get(object));}//对value定义排序规则,也即按照成绩高低升序System.out.println("\n成绩升序");Set<Entry<String,Integer>> entrySet = hashMap.entrySet();ArrayList<Entry<String, Integer>> al = new ArrayList<>(entrySet);Collections.sort(al,(o1,o2)->o1.getValue()-o2.getValue());for (Entry<String, Integer> entry : al) {System.out.println(entry.getKey()+" : "+entry.getValue());}

二、一些常用API

Arrays类

介绍:用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来 非常简单。

注意Arrays对数组,Collections对集合

一、

public static String toString(int[] a)

返回指定数组内容的字符串表示形式

int[] arr = {2,34,35,4,657,8,69,9}; // 打印数组,输出地址值 System.out.println(arr); // [I@2ac1fdc4String s = Arrays.toString(arr);System.out.println(s); // [2, 34, 35, 4, 657, 8, 69, 9]

二、

public static void sort(int[] a)

对指定的 int 型数组按数字升序进行排序

int[] arr = {24, 7, 5, 48, 4, 46, 35, 11, 6, 2}; System.out.println("排序前:"+ Arrays.toString(arr)); // 排序前:[24, 7, 5, 48, 4, 46, 35, 11, 6, 2] // 升序排序 Arrays.sort(arr); System.out.println("排序后:"+ Arrays.toString(arr));// 排序后:[2, 4, 5, 6, 7, 11, 24, 35, 46, 48]

注意

想要使用lambda对其排序的话,不能是基本类型 int double 而是Integer Double这些,而如果只使用默认排序的话,

Arrays.sort(arr, (o1,o2)->{return o2-o1;});//注意只能是 包装类数组!!!

超级大陷阱: 注意sort函数中的参数 fromindex 是inclusive toindex是exclusive ,也即 是不包含的!

此外,对于类中double属性排序, 可以这样:

Arrays.sort(arr,1,N+1,(o1,o2)->(int)Math.signum(o2.pp-o1.pp));

Collections类

java.utils.Collections是集合工具类,用来对集合(List)进行操作。部分方法如下:

public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中添加一些元素。public static void shuffle(List<?> list) 打乱顺序`:打乱集合顺序。public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。 public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。

Collections.addAll(list,1,2,3,4,5,100,300,100000);

直接使用第一个sort函数排序的 ,需要容器中的元素类实现了Comparable接口(Integer和String已经实现过了)

忽略我以前的关于cmp、compare函数的所有分析,而看现在的:根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数

简便思想:前 - 后是升序!!!!!

最新实验

public class Student implements Comparable<Student>{private String name;private Integer age;public Student(String name, Integer age) {super();this.name = name;this.age = age;}public Student() {super();}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + "]";}@Overridepublic int compareTo(Student o) {if(this.age==o.age)//先年龄升序再名字升序return this.name.charAt(0)-o.name.charAt(0);//名字首字母升序else {return this.age-o.age;//年龄升序}}public static void main(String args[]) {ArrayList<Student> al = new ArrayList<Student>();Collections.addAll(al, new Student("cchen",20),new Student("achen",20),new Student("bchen",21));System.out.println(al);Collections.sort(al);System.out.println(al);Collections.sort(al, (o1,o2)->{return o2.age-o1.age;});System.out.println(al);}}

[Student [name=cchen, age=20], Student [name=achen, age=20], Student [name=bchen, age=21]][Student [name=achen, age=20], Student [name=cchen, age=20], Student [name=bchen, age=21]][Student [name=bchen, age=21], Student [name=achen, age=20], Student [name=cchen, age=20]]

以前实验

class Student implements Comparable<Student>{String name;String ID;int M_score;@Overridepublic int compareTo(Student o) {//先分升,再名字升if (this.M_score==o.M_score)return this.name.charAt(0)-o.name.charAt(0);//分相同的话 按照名字升序 elsereturn this.M_score-o.M_score;}}public class Comparable_test {public static void main(String[] args) {ArrayList<Student> al=new ArrayList<>();al.add(new Student("wangchen","24100733",96));al.add(new Student("chenwang","24100759",96));al.add(new Student("fw","24100756",10));for (Student temp:al)System.out.print(" "+ temp);System.out.println();Collections.sort(al);for (Student temp:al)System.out.print(" "+ temp);}}输出:wangchen 24100733 96 chenwang 24100759 96 fw 24100756 10fw 24100756 10 chenwang 24100759 96 wangchen 24100733 96

对double类型的属性进行排序,

首先需要知道的是继承Comparable重写 CompareTo方发

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {

String类实现了这个接口,并完成了比较规则的定义,但是这样就把这种规则写死了,那比如我想要字符串按照第一个字符降序排列,那么这样就要修改String的源代码,这是不可能的了,那么这个时候我们可以使用

public static <T> void sort(List<T> list,Comparator<? super T> )方法灵活的完成,这个里面就涉及到了==Comparator==这个接口,位于位于java.util包下,排序是comparator能实现的功能之一

参数Comparator<? super T> 告诉我们 要想使用Collections.sort(),可以采取三种方法:

1.实现接口的类,然后创建对象

2.匿名内部类

3.Lambda

1.匿名内部类

public class CollectionsDemo3 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();list.add("cba");list.add("aba");list.add("sba");list.add("nba");Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o2.charAt(0) - o1.charAt(0);}});System.out.println(list);}}

又比如

class cmp implements Comparator<Integer>{@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;//降序 为什么}}public class Compareator_test {public static void main(String[] args) {ArrayList<Integer> al=new ArrayList<>();Collections.addAll(al,1,10,2,9,3,8);System.out.println(al);Collections.sort(al);//默认 升序System.out.println(al);Collections.sort(al, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}});//匿名内部类 降序System.out.println(al);System.out.println("-------------------");Collections.shuffle(al);Collections.shuffle(al);System.out.println(al);Collections.sort(al,new cmp());System.out.println(al);}}//结果:[1, 10, 2, 9, 3, 8][1, 2, 3, 8, 9, 10][10, 9, 8, 3, 2, 1]-------------------[3, 9, 2, 10, 8, 1][10, 9, 8, 3, 2, 1]

Math类

介绍:其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。

常量:Math.E Math.PIdouble abs(double a) :返回 double 值的绝对值。 double ceil(double a) ://返回大于等于( >= )给定参数的的最小整数//坐标轴右侧double floor(double a) ://返回小于等于(<=)给定参数的最大整数 。//坐标轴左侧long round(double a) ://返回接近参数的 long。(相当于四舍五入方法) double rint(double d)//返回最接近参数的整数值,若存在两个这样的数,则返回其中的偶数值Math.rint(101.500)=102.0;double min(double arg1, double arg2)//参数和返回值类型可以是int float long等double exp(double d)//返回自然数底数e的参数次方double log(double d)//返回参数的以自然数底数的对数值 return ln(d)double log10(double a)double pow(double base, double exponent)//返回第一个参数的第二个参数次方//注意开一个数的n次方根 ,用pow(base,分数)的形式double sqrt(double d)//返回参数的算术平方根double cbrt(double d)//计算立方根//nextUp(a) 返回比a大一点点的浮点数System.out.println(Math.nextUp(1.2));//输出1.2000000000000002//nextDown(a) 返回比a小一点点的浮点数System.out.println(Math.nextDown(1.2));//输出1.1999999999999997

也即:角度没啥用,就是单纯为了展示一下,弧度才是参与运算得到弦值的。

//角度180° = 弧度 πdouble sin(double d)//参数是弧度,返回值是正弦值double cos(double d)double tan(double d)double degrees = 45.0;double radians = Math.toRadians(degrees);System.out.format("%.1f 度的正弦值为 %.4f%n", degrees, Math.sin(radians));double asin(double d)//参数是正弦值,返回值是弧度double acos(double d)double atan(double d)double atan2(double y, double x)//atan2() 方法用于将矩形坐标 (x, y) 转换成极坐标 (r, theta)。返回所得角 弧度theta,该方法通过计算 y/x 的反正切值来计算相角 theta,范围为从 -pi 到 pi。//也即给定(x,y)求夹角的弧度

几个概念要清楚:

角度degrees弧度radians正弦值、余弦值、正切值 (比值)反正弦值、反余弦值、反正切值 (也即弧度,也即正弦对应的弧度)

double toDegrees(double d)double toRadians(double d)

Object类

object类是所有类的超类,它所具有的to string 、equals方法,其他类也一定有!,我们可以重写他们

1、toString 方法

public String toString()

返回该对象的字符串表示

默认的是返回该字符串内容就是对象的类型+@+内存地址值。但没多大用,因此我们要覆盖重写它

直接alt+shift+s 可以选择了

public class Person {private String name;private int age; @Overridepublic String toString() {return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';} }

小贴士: 在我们直接使用输出语句输出对象名的时候,其实通过该对象调用了其toString()方法。

2、equals方法

public boolean equals(Object obj)

判断参数对象是否与此对象“相等”。

若不覆盖重写,则进行默认的==运算符的对象地址比较,只要不是同一个对象,结果 必然为false。

简述String类中的equals方法与Object类中的equals方法的不同点。

答:String类中的equals方法是用来判断两个对象的内容是否相同,而Object 类中的equals方法是用来判断两个对象是否是同一个对象,所谓同一个对象指的是内存中的同一块存储空间。其实String类的euqals已经重写了了Object的equals了

调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。

1.默认:如果没有覆盖重写equals方法,那么Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,结果必然为false。

2.自定义:如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。例如:

@Override

public boolean equals(Object o) {

// 如果对象地址一样,则认为相同

if (this == o)

return true;

// 如果参数为空,或者类型信息不一样,则认为不同

if (o == null || getClass() != o.getClass())

return false;

// 转换为当前类型

Person person = (Person) o;

// 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果

return age == person.age && Objects.equals(name, person.name);

}

}

可以自动生成

3、hashcode&equals

/fenglibing/article/details/8905007

/weixin_38405253/article/details/91922340

通过前面这个例子,大概可以知道,先通过hashcode来比较,如果hashcode相等,那么就用equals方法来比较两个对象是否相等。

用个例子说明:上面说的hash表中的8个位置,就好比8个桶,每个桶里能装很多的对象,对象A通过hash函数算法得到将它放到1号桶中,当然肯定有别的对象也会放到1号桶中,如果对象B也通过算法分到了1号桶,那么它如何识别桶中其他对象是否和它一样呢,这时候就需要equals方法来进行筛选了。

1、如果两个对象equals相等,那么这两个对象的HashCode一定也相同

2、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置

Objects类

在JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表 示形式、比较两个对象。

在比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问 题

System类

1、currentTimeMillis方法

public static long currentTimeMillis()

返回以毫秒为单位的当前时间。获取当前系统时间与1970年01月01日00:00点之间的毫秒差值

2、arraycopy方法

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

将数组中指定的数据拷贝到另一个数组中。

数组的拷贝动作是系统级的,性能很高

import java.util.Arrays; public class Demo11SystemArrayCopy {public static void main(String[] args) {int[] src = new int[]{1,2,3,4,5}; int[] dest = new int[]{6,7,8,9,10}; System.arraycopy( src, 0, dest, 0, 3); /*代码运行后:两个数组中的元素发生了变化src数组元素[1,2,3,4,5]dest数组元素[1,2,3,9,10] */} }

Scanner类

Scanner sc = new Scanner(System.in);int a = sc.nextInt();整数Srting s =sc.next();字符串int num = new Scanner(System.in).nextInt(); 匿名对象

1、next

next() 方法遇见第一个有效字符(非空格,非换行符)时,开始扫描,也即忽略无用字符,,当遇见第一个分隔符或结束符(空格或换行符)时,结束扫描,获取扫描到的内容,即获得第一个扫描到的不含空格、换行符的单个字符串,与此同时会把遇到的空格、换行符、回车符留在缓冲区中。

2、nextLine

如果nextLine前有一个next,则nextLine()自动读取了被next()去掉的Enter作为他的结束符,所以nextLIne就读了个空。经过验证,我发现其他的next的方法,如double nextDouble() , float nextFloat() , int nextInt() 等与nextLine()连用时都存在这个问题,解决的办法是:在每一个 next()、nextDouble() 、 nextFloat()、nextInt() 等语句之后加一个nextLine()语句,将被next()去掉的Enter结束符过滤掉

3、hasNext

参考

使用无参的hasNext(),当执行到hasNext()时,它会先扫描缓冲区中是否有字符,有则返回true,继续扫描。直到扫描为空,这时并不返回false,而是将方法阻塞,等待你输入内容然后继续扫描。这样的话,它就像吃了炫迈口香糖根本停不下来。

当使用带有参数的hasNext重载方法,当扫描到的字符与参数值匹配时返回true

import java.util.*;public class ScannerKeyBoardTest{public static void main(String[] args){System.out.println("请输入若干单词,以空格作为分隔");Scanner sc = new Scanner(System.in);while(!sc.hasNext("#")) //匹配#返回true,然后取非运算。即以#为结束符号{System.out.println("键盘输入的内容是:"+ sc.next());}System.out.println("会执行的");}}

日期相关类

1 Date类

java.util.Date类 表示特定的瞬间,精确到毫秒。

毫秒:千分之一秒 1000毫秒=1秒

毫秒值->日期 构造

Date->毫秒值 gettime

public Date(): 获取当前系统的日期和时间public Date(long date):传递毫秒值,把毫秒值转换为Date日期

tips: 由于我们处于东八区,所以我们的基准时间为1970年1月1日8时0分0秒。

Date date = new Date();System.out.println(date);//Sat Nov 28 10:21:09 CST System.out.println(date.getTime());//1606530178632Date date1=new Date(0L);System.out.println(date1);//Thu Jan 01 08:00:00 CST 1970System.out.println(System.currentTimeMillis());//1606530069211Date date2 = new Date(1606530069211L);System.out.println(date2);//Sat Nov 28 10:21:09 CST

常用方法

Date类中的多数方法已经过时,常用的方法有:

public long getTime()把日期对象转换成对应的时间毫秒值。

2 DateFormat类

java.text.DateFormat是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。

格式化:按照指定的格式,从Date对象转换为String对象。解析:按照指定的格式,从String对象转换为Date对象。

构造方法

由于DateFormat为抽象类,不能直接使用,所以需要常用的子类java.text.SimpleDateFormat。这个类需要一个模式(格式)来指定格式化或解析的标准。构造方法为:

public SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。

参数pattern是一个字符串,代表日期时间的自定义格式。

格式规则

常用的格式规则为:

常用方法

DateFormat类的常用方法有:

public String format(Date date):将Date对象格式化为字符串。public Date parse(String source):将字符串解析为Date对象。

@Testpublic void test1(){//发现 :当yyyy个数是4、3、1个时 是 ,两个时是20, M d H m s 是一个两个都可以SimpleDateFormat sdf = new SimpleDateFormat("王晨元年yyyy-MM-ddHH点mm分ss秒");Date currentDate = new Date();String format = sdf.format(currentDate);System.out.println(format);}@Testpublic void test2() throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");String format = sdf.format(new Date());System.out.println(format);String str="-11-28 10-49-50";Date parsedate = sdf.parse(str);System.out.println(parsedate);}

实质:

​ SimpleDateFormat对象指定了一个转换格式

利用这个格式可以完成

String ->SimpleDateFormat对象的parse方法 -> Date

Date ->SimpleDateFormat对象的format方法 -> String

两段论:

先创建SimpleDateFormat对象,在构造方法中传递参数, 制定一个转换格式

利用这个转换格式,调用方法完成Date和String之间的转换

3 Calendar类

概念

java.util.Calendar是日历类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取日历类就是方便获取各个时间属性的

获取方式

Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象,如下:

Calendar静态方法

public static Calendar getInstance():使用默认时区和语言环境获得一个日历

例如:

import java.util.Calendar;public class Demo06CalendarInit {public static void main(String[] args) {Calendar cal = Calendar.getInstance();} }

常用方法

根据Calendar类的API文档,常用方法有:

public int get(int field):返回给定日历字段的值。public void set(int field, int value):将给定的日历字段设置为给定值。public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。

Calendar类中提供很多成员常量,代表给定的日历字段:

星期是 周日为1、周一为2、周二为3

月份是 1月为0,二月为1

import java.util.Calendar;public class CalendarUtil {public static void main(String[] args) {// 创建Calendar对象Calendar cal = Calendar.getInstance();// 设置年 int year = cal.get(Calendar.YEAR);// 设置月int month = cal.get(Calendar.MONTH) + 1;// 设置日int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);System.out.print(year + "年" + month + "月" + dayOfMonth + "日");} }

import java.util.Calendar;public class Demo07CalendarMethod {public static void main(String[] args) {Calendar cal = Calendar.getInstance();cal.set(Calendar.YEAR, );System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 1月17日}}

add方法可以对指定日历字段的值进行加减操作,如果第二个参数为正数则加上偏移量,如果为负数则减去偏移量。代码如:

import java.util.Calendar;public class Demo08CalendarMethod {public static void main(String[] args) {Calendar cal = Calendar.getInstance();System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 1月17日// 使用add方法cal.add(Calendar.DAY_OF_MONTH, 2); // 加2天cal.add(Calendar.YEAR, -3); // 减3年System.out.print(year + "年" + month + "月" + dayOfMonth + "日"); // 1月18日; }}

Calendar中的getTime方法并不是获取毫秒时刻,而是拿到对应的Date对象。

import java.util.Calendar;import java.util.Date;public class Demo09CalendarMethod {public static void main(String[] args) {Calendar cal = Calendar.getInstance();Date date = cal.getTime();System.out.println(date); // Tue Jan 16 16:03:09 CST }}

小贴士:

西方星期的开始为周日,中国为周一。

在Calendar类中,月份的表示是以0-11代表1-12月。

​ 日期是有大小关系的,时间靠后,时间越大。

BigInteger类

讲得很好

进制转换

三、迭代器

获取迭代器的方法:

Iterator<类> 迭代器名 = 容器名.iterator()

Iterator接口的常用方法如下:

public E next() :返回迭代的下一个元素public boolean hasNext() :如果仍有元素可以迭代,则返回 true

public class IteratorDemo {public static void main(String[] args) {Collection<String> coll = new ArrayList<String>();//多态coll.add("abc1");coll.add("abc2");coll.add("abc3");coll.add("abc4");Iterator<String> it = coll.iterator();while (it.hasNext()) {String s = it.next();System.out.println(s);}}}

当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。

四、C++与JAVA对比

1、JAVA迭代器与C++迭代器

C++

vector<int>::iterator iter = vec1.begin();string::iterator it=s.begin();map<int,string>::iterator iter_map=m.begin();auto iter=s.begin();

JAVA

Iterator<String> it = coll.iterator();

可见

C++是 数据结构<元素类型>::iterator

Java是 Iterator<元素类型>

2、数据结构定义方法

C++

list<int> lst1; stack<int> S;set<int> a;map<int,string> map1;

Java

ArrayList<String> list = new ArrayList<String>();//在JDK 7后,右侧泛型的尖括号之内可以留空,但是<>仍然要写。简化格式:ArrayList<String> list = new ArrayList<>();Collection<String> col=new ArrayList<String>();

可见他们几乎相同;区别是Java需要在堆里new一下

3、长度

五、可变参数

在JDK1.5之后,如果我们定义一个方法需要接受多个参数,并且多个参数类型一致,我们可以对其简化成如下格 式:

修饰符 返回值类型 方法名(参数类型… 形参名){ }

注意对于可变参数,也可以过去一个数组

public class ChangeArgs {public static void main(String[] args) {// 求 这几个元素和 6 7 2 12 2121int sum2 = getSum(6, 7, 2, 12, 2121);System.out.println(sum2);}//注意对于可变参数,也可以过去一个数组public static int getSum(int... arr) {int sum = 0;for (int a : arr) {sum += a;}return sum;}}

六、Lambda

lambda的使用处 必须是需要函数式接口对象的地方这个接口可以在方法参数中,可以是方法返回值,也可以创建一个对象时。代码块传递给函数式接口中的抽象方法,从而相当于形成了一个 接口的实现类对象

由于它的效果等价于匿名内部类,是一个对象,是一个已经重写了函数式接口中唯一抽象方法的类的对象,因此lambda的语句体中也是要完成重写的操作

面向对象的思想:

​ 做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情.

函数式编程思想:

​ 只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程

使用Lambda表达式的地方:一定是一个 需要 函数式接口对象 的地方,也即 Lambda表达式相当于一个实现类对象写Lambda表达式的方法:函数式接口中的抽象方法决定了Lambda表达式的写法 (函数参数和返回值)也即Lambda表达式方法的实现

典型的两段式:

函数式接口中的方法规定了 源参数 和 返回值, Lambda负责其中的运算处理过程

类似 接口中的方法声明中的参数负责 x和y lambda负责函数体 f(x)类中另外写了一个方法,负责整合 。且方法的某个或某些函数接口参数对象 ,负责供给消费一个映射断言判断方法,其他参数视情况具体而定。

Lambda表达式的标准格式为:

(参数类型 参数名称) -> { 代码语句 }

省略规则

在Lambda标准格式的基础上,使用省略写法的规则为:

小括号内参数的类型可以省略;如果小括号内有且仅有一个参,则小括号可以省略;如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。

例1:

@FunctionalInterfacepublic interface MyFunction {Integer getValue(Integer num); //参数是 一个整数,映射 一个整数, 映射规则自己定(在Lambda表达式中实现)}

public class Demo03_MyFunction {public static void main(String[] args) {Integer num1=operartion(100,(x)->x*x);System.out.println(num1);Integer num2=operartion(1000,(x)->++x);System.out.println(num2);}public static Integer operartion(Integer num,MyFunction mf){return mf.getValue(num);}}

对以上的理解:

编程目标是,实现对整数的处理(得到平方、自增1),

例2:

public interface MyFunction {public String getValue(String str);}

public class Demo01 {public static void main(String[] args) {String out=HandleStr("\t \t 王晨爱睡觉",str->str.trim() );System.out.println(out);}public static String HandleStr(String str,MyFunction mf) {return mf.getValue(str);}}

Lambda的语法非常简洁,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意:

使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法

无论是JDK内置的RunnableComparator接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。使用Lambda必须具有上下文推断

也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。

备注:有且仅有一个抽象方法的接口,称为“函数式接口”。

七、函数式接口

函数式接口在Java中是指:有且仅有一个抽象方法的接口。函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可 以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导备注:“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实 底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部 类的“语法糖”,但是二者在原理上是不同的。

接口是什么类型的,Supplier中的get方法就提供什么类型的数据;接口是什么类型的,Consumer中的accept方法就消费什么类型的数据;接口是什么类型的,Prediacate中的test方法就 接收什么类型的数据,然后判断返回一个bool值接口是什么类型的,Function中的apply方法就 接受什么类型T的数据,返回什么类型R的数据

1 Supplier < T >接口

java.util.function.Supplier 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对 象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象 数据。

public interface Supplier<T>{T get();}

指定接口是什么泛型,那么接口中的get方法就提供什么类型的数据

例如:

public ArrayList<Double> makeList(int num,Supplier<Double> sup){ArrayList<Double> list=new ArrayList<>();for(int i=0;i<num;i++)list.add(sup.get());}

上述函数的功能是得到一个存取Double的ArrayList集合,

集合元素的添加,用参数sup供给

参数num负责集合中的个数;

lambda表达式负责元素的获取规则

小结:消费的方式,供给的方法由Lambda指定,源和目的由接口指定

2 Consumer< T >接口

java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。

2.1 抽象方法accept方法

public interface Consumer<T>{void accept(T t)}

接口泛型是什么类型,accept方法就消费什么类型

参数 Consumer接口负责 消费

其他参数需要有一个提供消费品

2.2 默认方法:andThen

default Consumer<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) ‐> {accept(t); after.accept(t); }; }

例子:

public class Demo02_andThen {public static void main(String[] args) {String str="HeLLo";method(str,(s)-> System.out.println(s.toUpperCase()),(s)-> System.out.println(s.toLowerCase()));System.out.println("--------------------");method1(str,(s)-> System.out.println(s.toUpperCase()),(s)-> System.out.println(s.toLowerCase()),(s)-> System.out.println(s+"World"));}public static void method(String str, Consumer<String> con1,Consumer<String> con2){con1.andThen(con2).accept(str);/*上式等价于先后执行con1.accept(str);con2.accept(str);*/}//andThen可以连接很多public static void method1(String str, Consumer<String> con1,Consumer<String> con2,Consumer<String> con3){con1.andThen(con2).andThen(con3).accept(str);/*上式等价于先后执行con1.accept(str);con2.accept(str);con3.accept(str);*/}}

3 Predicate< T >接口

3.1 抽象方法:test

Predicate 接口中包含一个抽象方法:boolean test(T t)用于条件判断的场景:

public class Demo01 {public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<>();Collections.addAll(list,1,2,3,4,5,100,300,100000);System.out.println(list);ArrayList<Integer> outlist=getlist(list,(i)->i<5);System.out.println(outlist);}public static ArrayList<Integer> getlist(ArrayList<Integer> list, Predicate<Integer> pre){ArrayList<Integer> newlist=new ArrayList<>();for (Integer integer : list) {if(pre.test(integer))newlist.add(integer);}return newlist;}}

3.2 默认方法:and

既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个 Predicate 条件使用“与”逻辑连接起来实 现“并且”的效果时,可以使用default方法 and 。

public class Demo02_and {public static void main(String[] args) {String str="wangchen";boolean b=Judge(str,s->str.length()>5,s->str.startsWith("wang"));System.out.println(b);}public static boolean Judge(String str, Predicate<String> pre1,Predicate<String> pre2){//等价写法: //return pre1.test(str)&& pre2.test(str);return pre1.and(pre2).test(str);}}

3.3 默认方法:or

与 and 的“与”类似,默认方法 or 实现逻辑关系中的“或”。

public class Demo03_or {public static void main(String[] args) {String str="wangchen";boolean b=judge(str,s->s.length()>15,s->s.startsWith("wang"));System.out.println(b);}public static boolean judge(String str, Predicate<String> pre1,Predicate<String> pre2){// 等价写法// return pre1.test(str)||pre2.test(str);return pre1.or(pre2).test(str);}}

3.4默认方法:negate

public class Demo04_negate {public static void main(String[] args) {String str="wangchen";//是"wangchen"就返回false ,不是就返回trueboolean b=judge(str,s->s.equals("wangchennn"));System.out.println(b);}public static boolean judge(String str, Predicate<String> pre){return pre.negate().test(str);}}

信息筛选例子

4 Function <T,R> 接口

java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件, 后者称为后置条件。

4.1 抽象方法:apply

Function 接口中主要的抽象方法为:R apply(T t),根据类型T的参数获取类型R的结果。

使用的场景例如:将 String 类型转换为 Integer 类型。

public class Demo01 {public static void main(String[] args) {String str1="12345";method(str1,s ->Integer.parseInt(s) );String str2="wangchen";method(str2,s->s.length());}public static void method(String str, Function<String,Integer> fun){int out=fun.apply(str);System.out.println(out);}}

4.2 默认方法:andThen

Function 接口中有一个默认的 andThen 方法,用来进行组合操作。

自我理解: 和Consumer中的andThen有些许不同,

Consumer中的andThen是两个accept方法先后执行, 他们只有执行顺序的规定,而没有一些参数的依赖。

但是Function中的andThen是两个apply方法先后执行,不仅仅有执行顺序的规定,而且前者的返回值是后者的源

public class Demo02_andThen {public static void main(String[] args) {//判断字符串对应的数字是否大于100method("91",s->Integer.valueOf(s),i->i>100);}public static void method(String str, Function<String,Integer> fun1,Function<Integer,Boolean> fun2){Integer i=fun1.apply(str);Boolean b1=fun2.apply(i);System.out.println("b1="+b1);System.out.println("-------------------");Boolean b2 = fun1.andThen(fun2).apply(str);System.out.println("b2="+b2);}}

5 forEach

/ * @since 1.8*/default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}

八、Stream流

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循 环是做事情的方式,而不是目的。另一方面,使用线性循环就意味着只能遍历一次。如果希望再次遍历,只能再使 用另一个循环从头开始。

更加关注做什么而不是怎么做

该部分内容请参考IT黑马文件课程中的PDF

九、IO异常的处理

JDK7前处理

之前的入门练习,我们一直把异常抛出,而实际开发中并不能这样处理,建议使用try...catch...finally代码块,处理异常部分,代码使用演示: 注意定义资源时,不能在try中,因为如果定义了的话,它的作用于就仅限于try语句块了,finally里是无法释放的。

public class HandleException1 {public static void main(String[] args) {// 声明变量FileWriter fw = null;try {fw = new FileWriter("fw.txt");fw.write("黑马程序员"); //黑马程序员} catch (IOException e) {e.printStackTrace();} finally {try {if (fw != null) {fw.close();}} catch (IOException e) {e.printStackTrace();}}}}

JDK7的处理(扩展知识点了解内容)

还可以使用JDK7优化后的try-with-resource语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。

格式:

try (创建流对象语句,如果多个,使用';'隔开) {// 读写数据} catch (IOException e) {e.printStackTrace();}

代码使用演示:

public class HandleException2 {public static void main(String[] args) {// 创建流对象try ( FileWriter fw = new FileWriter("fw.txt"); ) {// 写出数据fw.write("黑马程序员"); //黑马程序员} catch (IOException e) {e.printStackTrace();}}}

JDK9的改进(扩展知识点了解内容)

JDK9中try-with-resource的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close,我们来了解一下格式。

改进前格式:

// 被final修饰的对象final Resource resource1 = new Resource("resource1");// 普通对象Resource resource2 = new Resource("resource2");// 引入方式:创建新的变量保存try (Resource r1 = resource1;Resource r2 = resource2) {// 使用对象}

改进后格式:

// 被final修饰的对象final Resource resource1 = new Resource("resource1");// 普通对象Resource resource2 = new Resource("resource2");// 引入方式:直接引入try (resource1; resource2) {// 使用对象}

改进后,代码使用演示:

public class TryDemo {public static void main(String[] args) throws IOException {// 创建流对象final FileReader fr = new FileReader("in.txt");FileWriter fw = new FileWriter("out.txt");// 引入到try中try (fr; fw) {// 定义变量int b;// 读取数据while ((b = fr.read())!=-1) {// 写出数据fw.write(b);}} catch (IOException e) {e.printStackTrace();}}}

其他

通过以下实验,发现对HashMap<Character,Hashset> map这个容器,通过character来的hashset,是获得,而不是复制

public static void main(String[] args) {HashSet<String> set = new HashSet<>();set.add("abc");set.add("cde");HashMap<Character, HashSet<String>> map = new HashMap<>();map.put('a',set);for(Character c:map.keySet()){System.out.println("key:"+c+"value:"+map.get(c));}HashSet<String> aset = map.get('a');aset.add("this is new");for(Character c:map.keySet()){System.out.println("key:"+c+"value:"+map.get(c));}}

Output:

key:a value:[abc, cde]

key:a value:[abc, this is new, cde]

浮点数的比较方法

1、

if (Math.abs(f1 - f2) <1e-6) {System.out.println("f1 and f2 are equal using threshold");} else {System.out.println("f1 and f2 are not equal using threshold");}

if (Double.isNaN(a) || Double.isNaN(b) || Double.isInfinite(a) || Double.isInfinite(b)) {return false;}return Math.abs(a - b) < 1e-6d;

2、

BigDecimal是不可变的,能够精确地表示十进制数字。需要注意的是,创建BigDecimal对象时,要使用参数为String的构造方法,不要使用构造参数为double的,如果非要使用double创建,一定要用valueOf静态方法,防止丢失精度。然后调用compareTo方法比较即可。

private void compareByBigDecimal() {BigDecimal f1 = new BigDecimal("0.0");BigDecimal pointOne = new BigDecimal("0.1");for (int i = 0; i < 11; i++) {f1 = f1.add(pointOne);}BigDecimal f2 = new BigDecimal("0.1");BigDecimal eleven = new BigDecimal("11");f2 = f2.multiply(eleven);System.out.println("f1 = " + f1);System.out.println("f2 = " + f2);if (pareTo(f2) == 0) {System.out.println("f1 and f2 are equal using BigDecimal");} else {System.out.println("f1 and f2 are not equal using BigDecimal");}}

运行输出:

f1 = 1.1f2 = 1.1f1 and f2 are equal using BigDecimal

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。