Math
1 2 3 4 5 6 7 8 public static double pow (double a, double b) ; public static long round (double a) ; public static double random () ; public static double sqrt (double a) ; public static double log (double a) ; public static double log10 (double a) ;
数组
初始化
1 2 3 4 5 6 7 8 9 10 11 int [] nums = new int [10 ];int [] nums = new int []{1 ,3 ,4 };int [] nums = {1 ,2 ,3 ,4 }; int [][] intss = new int [][]{ {1 ,2 ,3 }, {1 ,2 ,3 } };
数组具有Object 的所有方法,以及一个length属性
遍历数组
1 2 for (int i=0 ;i<nums.length;i++){....} for (int i:nums){....}
Arrays
这个是java提供操作数组的工具类,对于需要使用到排序的地方,基本数据类型只能从小到大,引用数据类型要么实现Comparable接口,要么提供Comparator的实现类
sort
有很多关于sort的重载方法,参数可以是基本数据类型,也可以是Object类型(因此可以为其他任何类型的数组排序,但是记得要实现Comparable接口或者提供Comparator的实现类
1 2 3 4 5 6 7 8 9 10 11 T[] nums = new T [10 ]; Arrays.sort(nums); Arrays.sort(nums,1 ,3 ) T[] nums = new T [10 ]; Arrays.sort(nums) Arrays.sort(nums,(a,b)->{ ..... })
parallelSort
这个方法和sort的用法是一样的,但是当数据量超过某一个值的时候,这个方法会采用并行的方式排序,在多核处理下优势就明显了,如果数据量少于某个值,依然使用sort方法排序,这个值是2^13 8192
1 2 3 4 5 6 7 8 9 10 11 public static void parallelSort (int [] a) { int n = a.length, p, g; if (n <= MIN_ARRAY_SORT_GRAN || (p = ForkJoinPool.getCommonPoolParallelism()) == 1 ) DualPivotQuicksort.sort(a, 0 , n - 1 , null , 0 , 0 ); else new ArraysParallelSortHelpers .FJInt.Sorter (null , a, new int [n], 0 , n, 0 , ((g = n / (p << 2 )) <= MIN_ARRAY_SORT_GRAN) ? MIN_ARRAY_SORT_GRAN : g).invoke(); }
binarySearch
必须是排序好的数组,利用二分查找找到值所在的位置,如果值不存在,返回它应该在的下标+1的相反数
1 2 3 4 nums = new int []{1 ,3 ,5 ,7 ,9 }; System.out.println(Arrays.binarySearch(nums,3 )); System.out.println(Arrays.binarySearch(nums,4 )); System.out.println(Arrays.binarySearch(nums,1 ,3 ,4 ));
这个方法无法像c++ 的 lower_bound 和 upper_bound 一样找到第一个等于某个值的位置,和第一个大于某个值的位置,需要我们自己去写二分查找
equals
比较两个数组元素是否相等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static boolean equals (Object[] a, Object[] a2) { if (a==a2) return true ; if (a==null || a2==null ) return false ; int length = a.length; if (a2.length != length) return false ; for (int i=0 ; i<length; i++) { Object o1 = a[i]; Object o2 = a2[i]; if (!(o1==null ? o2==null : o1.equals(o2))) return false ; } return true ; }
fill
填充数组的值
1 2 3 int [] nums = new int [10 ];Arrays.fill(nums,1 ); Arrays.fill(num,2 ,5 ,2 );
copyOf
复制数组的值变成另外一个一个数组
1 2 3 public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); }
copyOfRange
复制某个区间的值变成另外一个数组
1 2 3 public static <T> T[] copyOfRange(T[] original, int from, int to) { return copyOfRange(original, from, to, (Class<? extends T []>) original.getClass()); }
asList
将可变参数变成list
1 2 List<Integer> list = Arrays.asList(1 ,3 ,4 );
class java.util.Arrays$ArrayList 是这个方法产生的list对应的类,并不是ArrayList 哦
toString
将数组内容变成字符串,如果是基本数据类型就是拼接字符串,如果是引用数据类型就是执行元素里面的toString 方法
1 2 int [] nums = new int []{3 ,2 ,1 };System.out.println(Arrays.toString(nums));
deepToString
如果是多维数组,那么toString 是没有办法将他们都转化成字符串的,显示的是地址值
1 2 3 int [][][] ints = { {{1 , 2 , 3 }, {2 , 3 , 4 }},{{1 , 2 , 3 }, {2 , 3 , 4 }}};System.out.println(Arrays.toString(ints)) System.out.println(Arrays.deepToString(ints));
setAll
根据元素的下标设置元素的值
1 2 3 nums = new int [5 ]; Arrays.setAll(nums,a->a*a); System.out.println(Arrays.toString(nums));
stream
返回数组的流式数据,这个后面还会再总结
Collection
Collection 接口中定义了set接口以及list接口通用的方法,掌握这里面的方法,就不用重复看他们的子接口,实现类的方法了
提供方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int size () ; boolean isEmpty () ; boolean contains (Object o) ; Iterator<E> iterator () ; <T> T[] toArray(T[] a); boolean add (E e) ; boolean remove (Object o) ; boolean containsAll (Collection<?> c) ; boolean addAll (Collection<? extends E> c) ; boolean removeAll (Collection<?> c) ; boolean retainAll (Collection<?> c) ; void clear () ; Stream<E> stream () ; Stream<E> parallelStream () ;
这个接口就是站在一个很抽象的层面,不管你用何种数据结构,这些方法都是能够实现的,比如删掉某个元素,增加一个元素,是否包含某个元素等等
List接口
list接口是collection的子接口,因此它拥有collection的方法,list接口本身定义了很多方法,因此在它的子类中都会有实现,掌握list中的方法,就不用重复看其子类中的方法了
1 2 3 4 5 6 7 E get (int index) ; E set (int index, E element) ; void add (int index, E element) ; E remove (int index) ; int indexOf (Object o) ; int lastIndexOf (Object o) ; List<E> subList (int fromIndex, int toIndex) ;
对比一下 E remove(int index); boolean remove(Object o); 这两个方法,如果我们的泛型是Integer类型,那么就得格外小心了,你用Integer类型参数,调用的肯定是 boolean remove(Object o);你用的是int类型参数调用的肯定是E remove(int index);,如果你有一个Integer类型的参数,你又想删除它对应的下标,你必须将它变成int类型
ArrayList 和 linkedList 的区别在于底层实现
ArrayList 和 Vector 的区别在于 线程安全不安全, ArrayList是线程不安全的,Vector是线程安全的
这个接口感觉就具体些些了,我底层是按**“顺序”**(逻辑上一个元素紧挨一个元素),来存储数据的,因此肯定就有下标这么一说,那么就应该要提供关于下标的方法
Set接口
Set也是collection的子接口,这个接口并没有额外的定义方法,全部都是collection接口里面的方法,set接口的规定所有的数据必须唯一
SortedSet接口
实现了这个接口的类,里面的数据都是会排序的,输出里面数据的时候一定是按顺序来的
1 2 3 4 5 6 7 8 9 Comparator<? super E> comparator(); SortedSet<E> subSet (E fromElement, E toElement) ; SortedSet<E> headSet (E toElement) ; SortedSet<E> tailSet (E fromElement) ; E first () ; E last () ;
我们可以通过这个接口来找第一个大于等于某个数,大于某个数,最后小于等于某个数,或者小于某个数的数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class ListTest { public static void main (String[] args) { SortedSet<Integer> set = new TreeSet <Integer>(); set.add(3 ); set.add(7 ); set.add(5 ); set.add(6 ); System.out.println(set.tailSet(5 ).first()); System.out.println(set.tailSet(6 ).first()); System.out.println(set.headSet(5 ).last()); System.out.println(set.headSet(6 ).last()); } } 5 6 3 5
NavigableSet接口
这个是soreted的子接口,它多出来的功能,其实就是上面我们那段代码实现的功能
1 2 3 4 5 6 7 E lower (E e) ; E floor (E e) ; E ceiling (E e) ; E higher (E e) ; E pollFirst () ; E pollLast () ;
set的底层就是map, HashSet 是 对 HashMap对象的封装,TreeSet 是对 TreeMap的封装
TreeSet 实现类
这个是上面接口的实现类,它具有上面接口的所有方法,自己还提供了一些去实现这些接口的方法,因此记住了上面set,SortedSet,NavigableSet接口定义的方法,那么TreeSet也就差不多了
Queue接口
这个也是collection的子接口,拥有collection的全部方法,还自己提供了一些额外的方法哦
1 2 3 4 5 6 boolean add (E e) ; boolean offer (E e) ; E remove () ; E poll () ; E element () ; E peek () ;
刷题的时候推荐使用 offer,poll,peek
Deque接口
这个是queue接口的子接口,这个是双向队列,在单向队列的基础上额外提供了在头部插入,尾部删除的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void addFirst (E e) ; void addLast (E e) ; boolean offerFirst (E e) ; boolean offerLast (E e) ; E removeFirst () ; E removeLast () ; E pollFirst () ; E pollLast () ; E getFirst () ; E getLast () ; E peekFirst () ; E peekLast () ; void push (E e) ; E pop () ; E peek () ;
就不用java提供的stack的类了,它是继承了vector这个类再做的操作,我们可以直接使用双向队列替代
它的子实现类中 LinkedList底层用链表实现,ArrayDeque用数组实现
子实现类
在所有的子实现类中,一定有无参构造函数,和 只有一个参数,并且类型为collection的构造函数,其他的构造函数,要看具体的实现类的功能
下面举几个例子
1 2 3 4 5 6 7 8 public ArrayList () ;public ArrayList (Collection<? extends E> c) ;public ArrayList (int initialCapacity) ; public PriorityQueue () ;public PriorityQueue (int initialCapacity,Comparator<? super E> comparator) ; public PriorityQueue (Collection<? extends E> c) ;
Map
map 是一种具有映射关系的数据结构,一个key对应一个value
提供方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int size () ; boolean containsKey (Object key) ; boolean containsValue (Object value) ; V get (Object key) ; V put (K key, V value) ; V remove (Object key) ; void putAll (Map<? extends K, ? extends V> m) ; void clear () ; Set<K> keySet () ; Collection<V> values () ; Set<Map.Entry<K, V>> entrySet(); default v getOrDefault (Object key, V defaultValue) ; default V putIfAbsent (K key, V value) ; default boolean remove (Object key, Object value) ;
提供的内部接口Entry
1 2 3 4 K getKey () ; V getValue () ; V setValue (V value) ;
SortedMap接口
这个接口的定义就是里面的数据是按照key值来排序的
1 2 3 4 5 6 7 8 9 Comparator<? super K> comparator(); SortedMap<K,V> subMap (K fromKey, K toKey) ; SortedMap<K,V> headMap (K toKey) ; SortedMap<K,V> tailMap (K fromKey) ; K firstKey () ; K lastKey () ; Set<K> keySet () ; Collection<V> values () ; Set<Map.Entry<K, V>> entrySet();
NavigableMap接口
1 2 3 4 5 6 7 8 9 10 11 12 13 Map.Entry<K,V> lowerEntry (K key) ; K lowerKey (K key) ; Map.Entry<K,V> floorEntry (K key) ; K floorKey (K key) ; Map.Entry<K,V> ceilingEntry (K key) ; K ceilingKey (K key) ; Map.Entry<K,V> higherEntry (K key) ; K higherKey (K key) ; Map.Entry<K,V> firstEntry () ; Map.Entry<K,V> lastEntry () ; Map.Entry<K,V> pollFirstEntry () ; Map.Entry<K,V> pollLastEntry () ;
collections
这个是操作map,collection类型的工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public static <T extends Comparable <? super T>> void sort (List<T> list) ; public static <T> void sort (List<T> list, Comparator<? super T> c) ; public static <T> int binarySearch (List<? extends Comparable<? super T>> list, T key) ; public static <T> int binarySearch (List<? extends T> list, T key, Comparator<? super T> c) ; public static void reverse (List<?> list) ; public static void shuffle (List<?> list) ; public static void swap (List<?> list, int i, int j) ; public static <T> void fill (List<? super T> list, T obj) ; public static <T> void copy (List<? super T> dest, List<? extends T> src) ; public static <T extends Object & Comparable<? super T>> T min (Collection<? extends T> coll) ; public static <T> T min (Collection<? extends T> coll, Comparator<? super T> comp) ; public static <T extends Object & Comparable<? super T>> T max (Collection<? extends T> coll) ; public static <T> T max (Collection<? extends T> coll, Comparator<? super T> comp) ; public static void rotate (List<?> list, int distance) ; public static <T> boolean replaceAll (List<T> list, T oldVal, T newVal) ; public static int indexOfSubList (List<?> source, List<?> target) ;public static int lastIndexOfSubList (List<?> source, List<?> target) ; public static <T> Collection<T> unmodifiableCollection (Collection<? extends T> c) ; public static <T> Set<T> unmodifiableSet (Set<? extends T> s) ; public static <T> SortedSet<T> unmodifiableSortedSet (SortedSet<T> s) ; public static <T> NavigableSet<T> unmodifiableNavigableSet (NavigableSet<T> s) ; public static <T> List<T> unmodifiableList (List<? extends T> list) ; public static <K,V> Map<K,V> unmodifiableMap (Map<? extends K, ? extends V> m) ; public static <K,V> SortedMap<K,V> unmodifiableSortedMap (SortedMap<K, ? extends V> m) ; public static <K,V> NavigableMap<K,V> unmodifiableNavigableMap (NavigableMap<K, ? extends V> m) ; public static <T> Collection<T> synchronizedCollection (Collection<T> c) ; public static <T> Set<T> synchronizedSet (Set<T> s) ;public static <T> SortedSet<T> synchronizedSortedSet (SortedSet<T> s) ;public static <T> NavigableSet<T> synchronizedNavigableSet (NavigableSet<T> s) ;public static <T> List<T> synchronizedList (List<T> list) ;public static <K,V> Map<K,V> synchronizedMap (Map<K,V> m) ; public static <K,V> SortedMap<K,V> synchronizedSortedMap (SortedMap<K,V> m) ; public static <K,V> NavigableMap<K,V> synchronizedNavigableMap (NavigableMap<K,V> m) ;public static int frequency (Collection<?> c, Object o) ;
1 2 3 4 5 6 7 8 public static <E> Collection<E> checkedXXXXX () ; List list = new ArrayList (); list.add(1 ); list.add("111" ); list = Collections.checkedList(list,Integer.class); list.add("111" );
Lambda
Lambda 可以简化代码,用一个函数 就能替代一个函数式接口 实现并生成一个匿名类的对象 的代码,对比一下
1 2 3 4 5 6 7 8 9 10 new Thread (new Runnable () { @Override public void run () { System.out.println("hello" ); } }); new Thread (() -> System.out.println("hello" ));
感受到魅力了么
语法
1 2 3 4 5 6 7 (参数列表) -> { 执行语句; } Consumer<String> consumer = s-> System.out.println(s);
方法引用
如果一个类已经存在的方法和函数式接口中定义的抽象方法返回值相同,参数相同,且接口中的方法能访问到这个引用方法,这样就能够直接使用这个类或者这个类的对象的方法应用充当Lambda
我们可以理解成,传进来的参数我们可以找到哪个现成的方法能帮我们做,我们就用这个方法就行
通过类引用静态方法
这个就很简单了,就是引用一个类的静态方法
1 2 3 4 5 6 7 8 9 Function<String,Integer> function = Integer::valueOf; int apply = function.apply("10" );Function<String,Integer> function = (a)->{ return Integer.valueof(a); }
通过对象引用实列方法
这个也简单就是new一个对象然后使用它的方法
1 2 3 4 5 Consumer consumer2 = System.out::println;Consumer consumer2 = (p) -> { System.out.println(p); }
构造方法引用
1 2 3 4 5 Function<Integer,List<Integer>> function = ArrayList<Integer>::new ; Function<Integer,List<Integer>> function = (a)->{ return new ArrayList <Integer>(a); }
上面这几种其实都比较好理解,可以将方法引用写成Lambda的正常格式
像不像就是把传进来的参数给引用方法去执行,然后将引用方法非返回值返回去就OK了,可以理解成c++里面的函数指针
通过类引用实例方法
比如Object::toString,toString 明明是对象里面才能用的方法,为什么可以直接使用类名引用呢,其实编译器会将第一个参数作为对象调用这个方法,并且把后面的参数放入这个引用参数的后面
1 2 3 4 5 6 Function<Object,String> function1 = Object::toString; Function<Object,String> function1 = (o)->{ return o.toString(); }
函数式接口
函数式接口就是,接口中只能有一个抽象方法,这样就方便我们使用Lambda了,不过接口中还能有多个静态方法和default方法哦,不要被这个名字吓到哦,它其实也是一个接口,只不过只有一个抽象方法
常用函数式接口
Consumer
消费者
Supplier
生产者
Function
1 2 3 4 5 6 7 8 9 10 11 12 R apply (T t) ; default <V> Function<V, R> compose (Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } default <V> Function<T, V> andThen (Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); }
加工者
Predicate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 boolean test (T t) ; default Predicate<T> and (Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate<T> negate () { return (t) -> !test(t); } default Predicate<T> or (Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } static <T> Predicate<T> isEqual (Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }
检测者/测试者
Stream
steam 并不是一个容器,它只是对容器的增强功能,添加了很多便利的操作,列如查找,过滤,分组,排序等操作,而且还支持串行与并行两种模式,在并行的情况下能充分利用多核CPU的优势,总而言之stream 就是提供了搞笑且易于使用的数据处理方式
Stream的特点:
Stream不会自己存储数据
Stream的操作不会改变原对象,他们会产生一个新的Stream对象
Stream的操作是有延时的,它会等到需要结果的时候才会运行,也就是终端操作
Stream分为两个步骤,一个是中间操作,另外一个是终止操作,中间操作用来对数据加工,终止操作用来打印数据或者提取数据
使用stream刷题的时候,一定要引入Stream,像力扣这种默认只引入了java.util.*
我们需要手动引入: import java.util.stream.*
通过数组创建
可以通过Arrays的stream方法对组创建
1 IntStream stream1 = Arrays.stream(ints);
通过集合创建
1 2 3 Collection<Integer> collection = new ArrayList <>(); Stream<Integer> stream2 = collection.stream(); Stream<Integer> integerStream = collection.parallelStream();
通过Stream提供的方法创建
1 2 3 4 5 6 Stream<Integer> integerStream1 = Stream.of(1 , 2 , 4 , 5 ); Stream.generate(Math::random); Stream.iterate(0 ,a->a+1 );
中间操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Stream<T> filter (Predicate<? super T> predicate) ; <R> Stream<R> map (Function<? super T, ? extends R> mapper) ; IntStream mapToInt (ToIntFunction<? super T> mapper) ; LongStream mapToLong (ToLongFunction<? super T> mapper) ; DoubleStream mapToDouble (ToDoubleFunction<? super T> mapper) ; <R> Stream<R> flatMap (Function<? super T, ? extends Stream<? extends R>> mapper) ; IntStream flatMapToInt (Function<? super T, ? extends IntStream> mapper) ; LongStream flatMapToLong (Function<? super T, ? extends LongStream> mapper) ; DoubleStream flatMapToDouble (Function<? super T, ? extends DoubleStream> mapper) ; Stream<T> distinct () ; Stream<T> sorted () ; Stream<T> sorted (Comparator<? super T> comparator) ; Stream<T> peek (Consumer<? super T> action) ; Stream<T> limit (long maxSize) ; Stream<T> skip (long n) ;
终端操作
1 2 3 4 5 6 7 8 9 10 11 12 void forEach (Consumer<? super T> action) ;Object[] toArray(); T reduce (T identity, BinaryOperator<T> accumulator) ; Optional<T> reduce (BinaryOperator<T> accumulator) ; <R, A> R collect (Collector<? super T, A, R> collector) ; Optional<T> min (Comparator<? super T> comparator) ; Optional<T> max (Comparator<? super T> comparator) ; long count () ; boolean anyMatch (Predicate<? super T> predicate) ;boolean allMatch (Predicate<? super T> predicate) ;boolean noneMatch (Predicate<? super T> predicate) ;
像基本数据类型的流并不是Stream的子类,而是他的兄弟类,有时候我们需要将IntStream这个样的流变成Stream流使用他的方法,比如collect,可以使用boxed方法进行转变
实战
学完了这么些东西,有没有种蠢蠢欲动的感觉,什么?,迎面走来的你让我蠢蠢欲动(hahahahah)
数组变list
1 2 List<Integer> list = Arrays.stream(ints).boxed().collect(Collectors.toList())
list变数组
1 int [] ints1 = list.stream().mapToInt(a -> a).toArray();
其实这里利用的是java的自动装箱拆箱机制
1 2 3 4 5 6 7 8 9 10 11 public int fun(Integer a){ return a; } public Integer fun(int a){ return a; } System.out.println(fun(1)); System.out.println(fun(Integer.valueOf(2)));
Optional
Optional 是为了清晰地表达返回值中没有结果的可能性
这个能减少我们对null值的判断,就能减少不少的ifelse,配合上Lambda和函数式接口,简直可以起飞,而且感觉逻辑也比较清晰吧
不要过度使用 Optional 避免降低代码可读性和性能
调用了返回值为Optional的方法后,一定要做空值检查
用来在某些地方替代if - else 我觉得很不错
1 2 3 4 5 6 7 8 9 10 11 12 public static <T> Optional<T> empty () ; public static <T> Optional<T> of (T value) ; public static <T> Optional<T> ofNullable (T value) ; public T get () ; public boolean isPresent () ; public void ifPresent (Consumer<? super T> consumer) ; public Optional<T> filter (Predicate<? super T> predicate) ; public <U> Optional<U> map (Function<? super T, ? extends U> mapper) ; public <U> Optional<U> flatMap (Function<? super T, Optional<U>> mapper) ; public T orElse (T other) ; public T orElseGet (Supplier<? extends T> other) ;
举个例子吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class OptionalExample { public static void main (String[] args) { Optional<String> optional = Optional.of("Hello world" ); if (optional.isPresent()) { System.out.println(optional.get()); } optional.ifPresent(System.out::println); String nullSafeValue = optional.orElse("Default value" ); System.out.println(nullSafeValue); String mightBeNull = methodThatMightReturnNull(); Optional<String> optional2 = Optional.ofNullable(mightBeNull); optional2.ifPresent(System.out::println); } private static String methodThatMightReturnNull () { return (Math.random() < 0.5 ) ? "Hello world" : null ; } }
虽然省事,但是吧,咱们平常好像用的也不多