文章目录
一、泛型
1、简介:泛型是带一个或多个类型参数的类或接口。利用泛型可以编写更安全的程序。
常用的类型参数名: E(元素)、K(键)、N(数字)、T(类型)、V(值)
//泛型声明
public class 泛型类名<泛型类型参数T>{
private T value;
public 泛型类名() {} //默认构造方法
public 泛型类名(T value) { //带参数构造方法
this.value = value;
}
public T get(){ //成员方法
return value;
}
public void set(T value){
this.value = value;
}
}
//实例化泛型类对象
泛型类名 <实际类型> 对象名 = new 泛型类名<>();
Node <Integer> intNode = new Node<>();
//调用成员方法
对象名.setData(new Integer(999));
对象名.getData();
//多个类型参数的泛型
//两个参数的泛型接口
public interface Entry<K,V>{
public K getKey(); //抽象方法
public V getValue();
}
//实现泛型接口
public calss Pair<K,V> implements Entry<K,V>{ //注意接口和类都带两个参数
private K key;
private V value;
public Pair(K key, V value) { //构造方法,注意类型 K、V
this.key = key;
this.value= value;
}
//实现接口的抽象方法...
}
//创建泛型类实例
Pair<String,String> p = new Pair<>("china","Beijing");
2、泛型方法
简介:带类型参数的方法,有静态方法和非静态方法
//eg: 交换两个元素的位置
public class 类{
public static <T> void 方法名(T[] array,int i,int j) { //注意在返回值之前加上<类型>
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
...
//在Integer数组中交换两个元素的位置
Integer[] numbers = {1, 3, 5, 7};
类名.<Integer>方法名(numbers, 0, 3);
//参数类型<Integer>可省略,即类名.方法名(numbers, 0, 3);
}
3、类型参数
(1)通配符(?):接收任何类型
public static void printList(List<?> list){ //表示该方法可接受的元素是任何类型的List对象
for(Object element : list){
System.out.println(element);
}
}
(2)有界类型参数:限制传递给泛型的参数的类型
概念:
上界用extends指定,例如, List<? extends Number>
下界用super指定,例如, List<? super Integer>
二、集合
概念:处理对象组,集合都是泛型类型
导包:import java.util.*
两个基本接口:
(1)Collection
(2)Map
对应的子接口和实现类:
1、Collection接口
对集合的操作方法
//1、基本操作
boolean add(E e)
boolean remove(Object o)
boolean contains(Object o)
boolean isEmpty()
int size()
//2、批量操作
boolean addAll(Collection<? extends E> c) //将集合c的所有元素添加到当前集合中
boolean removeAll(Collection<?> c)
default boolean removeIf(Predicate<? super E> filter)
boolean containsAll(Collection<?> c)
boolean retainAll(Collection<?> c) //在当前集合中只保留集合c中指定的元素
void clear()
//3、数组操作
Object[] toArray() //返回包含集合中所有元素的对象数组
<T> T[] toArray(T[] a) //可设置返回数组的元素类型
//4、流(String)操作
public default Stream<E> stream() //返回顺序流对象
public default Stream<E> paralellStream() //返回并行流对象
(1)List接口及实现类
1、简介:List接口实现一种对象列表的结构,通过从0开始的下标访问List中的元素。List中可以包含重复元素。
2、List接口的实现类:
3、基本操作
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 from, int to) //返回从from到to的一个子线性表
4、ArrayList类
(1)简介:ArrayList类实际上实现了一个变长的对象数组,其元素可以动态地增加和删除。它的定位访问时间是常量时间。
(2)构造方法
ArrayList() //空的数组线性表对象,初始容量为10
ArrayList(Collection c) // 用集合c的元素创建数组线性表对象
ArrayList(int initialCapacity) //空的数组线性表对象,指定初始容量
(3)eg:
注意声明对象的时候一定要在前面加上 <类型>
由于声明了类型之后编译器可以自动识别,所有后面有的地方的<类型>省略了,如果以后对比源码发现有的代码有<类型>,有的没有,不要太纠结这个问题。
List <类型> 对象名 = new ArrayList<>();
对象名.add(元素);
对象名.add(下标,元素);
//遍历集合
//方法1:for循环
for(int i=0;i<对象名.size();i++){
System.out.print(对象名.get(i)+" ");
}
//方法2:增强for循环 顺序遍历
for(类型 别名:对象名){
System.out.print(别名);
}
//方法3:迭代器Interator接口 顺序遍历
for(Iterator iterator = 对象名.iterator();iterator.hasNext();){
System.out.println(iterator.next());
}
//双向迭代器ListInterator 可反向遍历,也可进行add()、set()、remove()
ListIterator iterator = 对象名.listIterator();
while(iterator.hasNext()) // 将迭代器指针移到线性表末尾
iterator.next();
while (iterator.hasPrevious()) // 从后向前访问线性表每个元素
System.out.println(iterator.previous());
(4)数组转为List对象
使用java.util.Arrays类的静态方法:==asList()==方法
List<类型> list集合名 = Arrays.asList(元素1,元素2...);
(2)Set接口及其实现类
简介:类似于数学上的集合,不允许元素重复,用树结构来存储元素
Set接口的实现类:HashSet类、TreeSet类
1、HashSet类
(1)简介:HashSet类用散列方法存储元素,具有最好的存取性能,但元素没有顺序。
(2)构造方法:
HashSet() //初始容量是16,默认装填因子是0.75。
HashSet(Collection c) //使用集合c元素
HashSet(int initialCapacity) //指定初始容量
Set <类型> 对象名 = new HashSet<>();
对象名.add(元素);
//用Set对象实现集合操作
s1.addAll(s2):实现集合s1与s2的并运算。
s1.retainAll(s2):实现集合s1与s2的交运算。
s1.removeAll(s2):实现集合s1与s2的差运算。
s1.containsAll(s2):如果s2是s1的子集,该方法返回true。
2、TreeSet类
(1)简介:它使用红-黑树算法为元素排序。添加到TreeSet中的元素必须是可比较的,即元素的类必须实现Comparable接口。
(2)构造方法
TreeSet()
TreeSet(Collection c) //按照自然顺序为集合元素排序
TreeSet(Comparator c) //按给定的比较器c的规则排序
//eg:自然排序(从小到大)
Set<Integer> ts = new TreeSet<>();
Integer[] s = new Integer[]{88,-12,56,90};
for (int i = 0; i < s.length; i++){
ts.add(s[i]); //向TreeSet类的对象ts添加元素,TreeSet中的元素将自动排序
}
System.out.println(ts); // {four,one,three,two}
//eg:自定义的比较器排序
Set<Integer> ts = new TreeSet<>(new Comparator<Integer>(){
public int compare(Integer o1, Integer o2){
return o2.compareTo(o1); //从大到小
}
});
//或者用nb的Lambda表达式
Set<Integer> ts = new TreeSet<>((o1,o2) -> o2.compareTo(o1));
(3)Queue接口及其实现类
简介:Queue接口以先进先出的方式排列其元素,称为队列(queue)。
实现类:
//Queue接口常用方法
//操作失败抛出异常
boolean add(E e) //向队列中插入指定元素e
E remove() //返回队列头元素,同时将其删除
E element() //返回队列头元素,不将其删除
//操作含义和上面一样,但操作失败返回值
boolean offer(E e)
E poll()
E peek()
Deque接口常用方法
LinkedList类更灵活,允许插入null元素,适合经常在线性表头部增加元素或删除元素
//eg: ArrayDeque
int [] elements = {1,2,3,0,7,8,9};
ArrayDeque<Integer> queue = new ArrayDeque<>();
queue.addFirst(5); // 5
for(int i = 0; i < 3; i++) {
queue.addFirst(elements[i]); // 3 2 1 5
}
for(int i = 4; i<7;i++) {
queue.offerLast(elements[i]); // 3 2 1 5 7 8 9
}
for(Integer v : queue) {
System.out.print(v + " ");
}
// 队列大小:queue.size());
2、Map接口
1、简介:存储“键/值”对的对象。在Map中存储的关键字和值都必须是对象,并要求关键字是唯一的,而值可以重复。
2、Map接口实现类
HashMap类:以散列方法存放“键/值”对
TreeMap类:默认按键 对“键/值”对 进行排序
3、基本操作
public V put(K key, V value) //添加 键值对
public V get(Object key)
public V remove(Object key)
public void clear()
public Set<K> keySet() //返回由键组成的集合对象
public Collection<V> values() //返回由值组成的集合对象
//HashMap类 eg:
String[] country={"中国","印度","澳大利亚"};
String[] capital={"Beijing","New Delhi","Canberra"};
Map<String, String> m = new TreeMap<>();
for(int i = 0;i<country.length;i++)
m.put(country[i], capital[i]);
3、Collections类
简介:java.util .Collections类是工具类,提供了若干static方法实现集合对象的操作。大多是对List操作。
主要操作:
Integer []num = {30,-20,99, 50, 0, 8};
List<Integer> list = Arrays.asList(num);
1、排序
Collections.sort(list);
2、查找
Collection.binarySearch(list,元素);
3、重排(打乱次序)
Collections.shuffle(list);
4、求极值
Collections.max(list); //最大值
5、反转
Collections.reverse(list);
三、Stream API
(1)流(Sream)简介:
①流(stream)指的是数据流,它像一个管道,可以将数据从源传输到目的地。流仅用来移动数据,不能像集合一样向流中添加元素。
②流可分为顺序流和并行流。使用流的主要原因是它支持顺序的和并行的聚集操作。例如,可以很容易地排序、过滤或转换流中的元素。
③Stream API 中的Stream接口最常用。Stream对象可用来传输任何类型的对象。
导入包:import java.util.stream.*;
(2)Stream接口中常用方法
中间操作:将一个流转换成另一个流
终止操作:产生一个最终结果
1、各种流操作
(1)创建流
方法一:Stream.of()方法
Stream<类型> 流对象名stream = Stream.of(数组名或元素);
方法二:Arrays.stream()方法
Stream<类型> stream = Arrays.stream(数组名);
方法三:集合接口的stream()
List<类型> 集合对象名list = new ArrayList<>();
Stream<类型> stream = list.stream(); //顺序流
Stream<类型> stream = list.parallelStream(); //并行流
(2)连接流、排序流、限制流、过滤流
concat(流1,流2):连接两个流
sorted():进行排序,依然是两种:自然排序和自定义比较器排序
limit(元素个数):返回一个包含原始流前n个原素的新流
filter(规则):返回一个包含按某种规则选择的元素的新流。规则可用Lambda表达式表示
map(转换函数):对原始流进行某种形式的转换,返回一个新流
map(转换函数)举例:
map(String::toLowerCase) //转成小写
map(String::toUpperCase).map(x->x.substring(0,1)); //转成大写、取出元素的第一个字符
//eg:两个流连接、自然排序、输出
Stream<String> stream1 = Stream.of("","");
Stream<String> stream2 = Stream.of("","");
Stream<String> stream = Stream.concat(stream1,stream2).sorted().forEach(System.out::println);
//eg:比较器排序(长度长的排在前面)、返回前3个元素
String[] words = {"","","",""};
Stream<String> stream4 = Stream.of(words).sorted(
Comparator.comparing(String::length).reversed().limit(3));
//eg:过滤流,过滤长度>=4的元素
Stream<String> stream5 = Stream.of(words).filter(x->x.length()>=4);
(3)流规约
简介:从流中获得一个结果的方法为规约方法。规约是终止操作。
归约方法:
count():流中元素个数
max()和min():返回流中最大值和最小值。返回一个Optional<T>类型的值,它可能会封装返回值,当流为空时没有返回。
String[] words = {"","","",""};
long n = Stream.of(words).count();
Optional <String> largest = Stream.of(words).max(String::compareTo); //返回元素首字母Unicode码的大
System.out.println(largest.get());
(4)收集结果
1、stream.toArray() :将流中所有元素转换成一个Object[]类型数组
如果要返回指定类型的数组,则给toArray()传递一个构造方法引用,
//返回一个字符串数组
String[] result = stream.toArray(String[]::new);
2、Stream.collect(Collectors.实例方法):将流中元素收集到另一个集合
List<String> result = stream.collect(Collectors.toList()); //列表
Set<String> result = stream.collect(Collectors.toSet()); //集合
TreeSet<String> result = stream.collect(Collectors.toCollection(TreeSet::new)); //Set中的TreeSet
2、基本类型流
1、简介:上面说的流是对象流,基本类型流有IntStream类型(short、char、byte、boolean),DoubleStream类型(float)
2、创建基本类型流
//创建IntStream
1、IntStream.of()方法
IntStream stream = IntStream.of(1, 1, 2, 3, 5, 8, 11);
2、Arrays.stream()方法
stream = Arrays.stream(整型数组, 开始下标, 结束下标);
3、一些方法
(1)sum()、average()、max()、min()
int[] integers = new int[] (1, 1, 2, 3, 5, 8, 11);
int min = Arrays.stream(integers).min().getAsInt();
int sum = Arrays.stream(integers).sum();
double avg = Arrays.stream(integers).average().getAsDouble();
(2)IntStream拥有range()和rangeClosed()静态方法,可以产生步长为1的一个整数范围。
int sum = IntStream.range(1, 10).sum(); // returns 45
int sum = IntStream.rangeClosed(1, 10).sum(); // returns 55
3、并行流
简介:并行流可以提高效率,但不是所有情况下并行流都比顺序流要快
创建并行流
paralellStream():可以从任何集合获得一个并行流。
Stream<String> 并行流名 = 集合名.parallelStream();
paralell():将顺序流转换成并行流。
Stream<String> 并行流名 = Stream.of(顺序流名).paralell();
// 计算第n个斐波那契数方法
public static long fibonacci(long n) {
if (n == 1 || n == 2) {
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
...
List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 41, 42);
numbers.parallelStream().map((input) -> fibonacci(input)).forEach(System.out::println);