Java基础
集合
1.Collection接口
Collection 是 List 和 Set 的父接口。
常用方法如下:
package com.java.day16;
import java.util.ArrayList;
import java.util.Collection;
/**
*测试Collection接口的常用方法
*/
public class Demo {
/**
* 范型是jdk 5.0以后有的
* Collection<String> coll = new ArrayList<String>();
* 后面的<>里可以不写
* Collection<String> coll = new ArrayList<>();
* <>里必须装引用类型
*/
public static void main(String[] args) {
Collection<String> coll1 = new ArrayList<>();
Collection<Integer> coll2 = new ArrayList<>();
coll2.add(1);
//add()添加
coll1.add("hello");
coll1.add("zhou");
//isEmpty()判断集合有没有元素
boolean b = coll1.isEmpty();
System.out.println(b);
//size()容器里元素个数
System.out.println(coll1.size());
//判断集合中是否包含元素
System.out.println(coll1.contains("hello"));
//删除元素
coll1.remove("hello");
System.out.println(coll1.size());
//清空容器
coll1.clear();
System.out.println(coll1.size());
}
}
package com.java.day16;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
*遍历集合的方法
*/
public class Demo2 {
public static void main(String[] args) {
Collection<String> coll1 = new ArrayList<>();
coll1.add("hello");
coll1.add("zhou");
coll1.add("lala");
//第一种方法 增强for循环
for(String str : coll1) {
System.out.println(str);
}
System.out.println("=======================================");
//第二种方法 迭代器
Iterator<String> it = coll1.iterator();
while(it.hasNext()) {
String str = it.next();
System.out.println(str);
}
System.out.println("=======================================");
//第三种 lambda表达式
coll1.forEach(a->System.out.println(a));
}
}
package com.java.day16;
import java.util.ArrayList;
import java.util.Collection;
/**
*和集合相关的方法
*/
public class Demo3 {
public static void main(String[] args) {
Collection<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");
//c1集合中是否包含c2
System.out.println(c1.containsAll(c2));
//c1中添加c2
c1.addAll(c2);
c1.forEach(str->System.out.println(str));
//c1中删除c2
c1.removeAll(c2);
c1.forEach(str->System.out.println(str));
}
}
-
List接口
有序的、元素可重复
2.1 ArrayList
线性表
底层实现是数组,默认容量为10,容量不够进行扩容。
常用方法如下:
package com.java.day16;
import java.util.ArrayList;
import java.util.List;
/**
*ArrayList常用方法
*/
public class Demo4 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//添加
list.add("hello");
list.add(0, "add");
list.forEach(str->System.out.println(str));
//修改
list.set(1, "1111");
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));
}
}
}
package com.java.day16;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Demo5 {
//集合转换成数组
public static void test1(){
List<String> list = new ArrayList<>();
list.add("hello");
list.add(0, "add");
List<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(2);
list2.add(12);
list2.add(23);
Object[] obj = list2.toArray();
int sum = 0;
for(Object o : obj) {
sum += (Integer)o;
}
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 = list.toArray(new String[list.size()]);
Arrays.sort(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();
};
};
//数组转换成集合
//注意:给集合排序使用的是Collections的sort方法
public static void test2() {
String[] str = {"hello", "abeeec", "fhhhgff"};
List<String> list = Arrays.asList(str);
//使用默认的排序规则
Collections.sort(list);
System.out.println(list);
//重新定义排序规则
//Collections.sort(list, com);
Collections.sort(list, (o1, o2) -> o1.length() - o2.length());
System.out.println(list);
}
public static void main(String[] args) {
//test1();
test2();
}
}
练习
按照学生成绩排序--------有两种方法,下面的代码将两种方法写在了一起。
第一种方法: 使用的是Collections的sort方法自定义排序,第二个参数传递Comparator的实现类;
第二种方法:要排序的类实现Comparable接口,重写compareTo方法,再使用Collections的sort方法传递一个参数。
package com.java.day16;
public class Student {
private String name;
private int score;
public Student() {
super();
// TODO Auto-generated constructor stub
}
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;
}
@Override
public String toString() {
return "Student [name=" + name + ", score=" + score + "]";
}
}
package com.java.day16;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
*练习:按照学生成绩排序
*/
public class Test {
public static void main(String[] args) {
//排序第一种方法
List<Student> list = new ArrayList<Student>();
list.add(new Student("张三", 80));
list.add(new Student("李四", 90));
list.add(new Student("王五", 95));
Collections.sort(list, (o1, o2)-> o1.getScore() - o2.getScore());
System.out.println(list);
//list.forEach(stu-> System.out.print(stu.getName()+" "));
//排序第二种方法
List<Student2> list2 = new ArrayList<Student2>();
list2.add(new Student2("张三", 80));
list2.add(new Student2("李四", 90));
list2.add(new Student2("王五", 95));
Collections.sort(list2);
System.out.println(list2);
}
}
package com.java.day16;
public class Student2 implements Comparable<Student2>{
private String name;
private int score;
public Student2() {
super();
// TODO Auto-generated constructor stub
}
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;
}
@Override
public String toString() {
return "Student [name=" + name + ", score=" + score + "]";
}
@Override
public int compareTo(Student2 o) {
return this.score - o.score;
}
}
-
泛型
java泛型设计原则:编译不出错,运行时就不会出现类型转换异常。
3.1 泛型类
class TestObj< T >{
private T obj;
private int age;
private String name;
…
}
如果想用一个类来描述学生和员工,学生有学号的属性,员工有工资的属性,那么就可以使用泛型类,代码如下:
package com.java.day17;
public class TestObj<T> {
private T data;
private String name;
public TestObj() {
super();
// TODO Auto-generated constructor stub
}
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;
}
@Override
public String toString() {
return "TestObj [data=" + data + ", name=" + name + "]";
}
}
package com.java.day17;
public class Demo1 {
public static void main(String[] args) {
TestObj<String> stu = new TestObj<>();
stu.setName("zhou");
stu.setData("20171612245");
System.out.println(stu);
TestObj<Double> emp = new TestObj<>();
emp.setName("张三");
emp.setData(12000.5);
System.out.println(emp);
}
}
3.2 泛型方法
泛型方法所在的类不一定是泛型类。
//泛型方法------输出任意数据类型的数组元素
public static <T> void showData(T[] a) {
for(T t : a) {
System.out.print(t+" ");
}
}
3.3 泛型接口
interface Inf< T >{
}
package com.java.day17;
//泛型接口
interface Demo2Inter<T>{
void show(T t);
}
//子类明确了泛型接口的数据类型
class Demo2Impl1 implements Demo2Inter<String>{
@Override
public void show(String t) {
System.out.println(t);
}
}
//子类不明确泛型接口的数据类型
class Demo2Impl2<T> implements Demo2Inter<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
public class Demo2 {
public static void main(String[] args) {
Demo2Inter<String> di1 = new Demo2Impl1();
di1.show("di1");
Demo2Inter<String> di2 = new Demo2Impl2<>();
di2.show("di2");
}
}
3.4 泛型的使用—通配符
通配符---- ? 表示任意数据类型
List< Object >和List< String >不存在继承关系,代码如下:
package com.java.day17;
import java.util.ArrayList;
import java.util.List;
public class Demo3 {
public static void test(List<Object> list) {
for(Object object : list) {
System.out.println(object);
}
}
public static void main(String[] args) {
//List<Object> list = new ArrayList<>();
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
//test(list);//报错,因为List< Object >和List< String >不存在继承关系
}
}
package com.java.day17;
import java.util.ArrayList;
import java.util.List;
public class Demo3 {
public static void test(List<?> list) {//使用了通配符,表示任意数据类型
for(Object object : list) {
System.out.println(object);
}
}
public static void main(String[] args) {
//List<Object> list = new ArrayList<>();
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
test(list);
}
}
3.5 设置通配符的上限
List<? extends Number>
package com.java.day17;
import java.util.ArrayList;
import java.util.List;
public class Demo3 {
//通配符的上限
public static void test2(List<? extends Number> list) {
for(Number number : list) {
System.out.println(number);
}
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
test2(list);
}
}
3.6 设置通配符的下限
List<? super Number>
package com.java.day17;
import java.util.ArrayList;
import java.util.List;
public class Demo3 {
//通配符的下限
public static void test3(List<? super Number> list) {
for(Object number : list) {
System.out.println(number);
}
}
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.add(1);
list.add(2);
test3(list);
}
}
3.7 通配符的错误使用
class A<?>{}
public <?> void t(List<?> list){}
List<?> list = new ArrayList<?>();
-
Stream类型
和io没有任何关系
流式思想:像生产流水线一样,一个操作接一个操作。
使用流操作集合更高效
4.1 Stream的特性
1.stream不存储数据
2.stream不改变源数据
3.stream的延迟执行特性
4.2 使用Stream流的步骤
数据源→转换成流→操作1→操作2→……
数据源(source):可以是集合、数组等。
获取流:
public static void test1() {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
//把集合变成了流
Stream<String> stream1 = list.stream();
Integer[] num = {1, 2, 3};
//把数组变成流
Stream<Integer> stream2 = Stream.of(num);
stream2.forEach(e->System.out.println(e));
//stream2.forEach(e->System.out.println(e));//报错,流只能使用一次
}
4.3 流的常用方法
//stream常用方法
public static void test2() {
//filter 方法用于通过设置的条件过滤出元素
Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6,7,8);
Stream<Integer> numStream = stream2.filter(e -> e % 2 != 0);
numStream.forEach(e -> System.out.println(e));
System.out.println("================================");
//2.map 方法用于映射每个元素到对应的结果
stream2 = Stream.of(1,2,3,4);
stream2.map(e -> e * e).forEach(e -> System.out.println(e));
System.out.println("================================");
//3.limit 方法用于获取指定数量的流
stream2 = Stream.of(1,2,3,4);
stream2.limit(3).forEach(e -> System.out.println(e));
System.out.println("================================");
//4.跳过前n个stream.skip
stream2 = Stream.of(1,2,3,4);
stream2.skip(2).forEach(e -> System.out.println(e));
System.out.println("================================");
//5.返回数量count
stream2 = Stream.of(1,2,3,4);
System.out.println(stream2.count());
System.out.println("================================");
//6.流的连接Stream.concat(stream1,stream2)
stream2 = Stream.of(1,2,3,4);
Stream<Integer> stream3 = Stream.of(5,6,7,8);
Stream.concat(stream2, stream3).forEach(e -> System.out.println(e));
System.out.println("================================");
//7.可以把流转换为 List 类型:collect(Collectors.toList());
stream2 = Stream.of(1,2,3,4);
System.out.println(stream2.collect(Collectors.toList()));
System.out.println("================================");
//8.求和的方法reduce(0, (x, y) -> x + y)
stream2 = Stream.of(1,2,3,4);
System.out.println(stream2.reduce(0, (x, y) -> x + y));
System.out.println("================================");
//9.去重distinct()
stream2 = Stream.of(1,2,3,4,3);
stream2.distinct().forEach(e -> System.out.println(e));
System.out.println("================================");
//10.排序:sorted()
stream2 = Stream.of(1,4,3,2);
stream2.sorted().forEach(e -> System.out.println(e));
}
-
List集合的实现类
Linkedlist (线程不安全) 和 Vector (线程安全)
5.1 Linkedlist
双向链表
Linkedlist 和 Arraylist 都是线程不安全的
5.2 Vector
Vector 是线程安全的
-
Set集合
无序、元素不重复
不重复:先判断hashCode(),再判断equals(),如果返回true,表示一个对象,否则是不同对象。
6.1 hashSet
HashSet基于HashMap的实现,HashSet的元素是map中的key。
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("张三");
set.add("张三");
set.add("李四");
set.add("王五");
set.remove("王五");
set.forEach(System.out::println);
}
6.2 TreeSet
会排序
TreeSet的元素必须是有排序规则的对象,否则会运行时异常
package com.java.day17;
import java.util.TreeSet;
class Emp{
private String name;
private int age;
public Emp() {
super();
// TODO Auto-generated constructor stub
}
public Emp(String name, int age) {
super();
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;
}
@Override
public String toString() {
return "Emp [name=" + name + ", age=" + age + "]";
}
}
public class Demo7 {
public static void test1() {
TreeSet<String> set = new TreeSet<>();
set.add("a");
set.add("b");
set.add("c");
set.forEach(System.out::println);//a b c 排序输出
}
public static void test2() {
TreeSet<Emp> set = new TreeSet<>((emp1, emp2)-> emp1.getName().length() - emp2.getName().length());
set.add(new Emp("admin", 12));
set.add(new Emp("bff", 13));
set.add(new Emp("abmin", 14));
set.forEach(System.out::println);//Emp [name=bff, age=13] Emp [name=admin, age=12] 排序输出
}
public static void main(String[] args) {
//test1();
test2();
}
}
-
Map
HashMap 和 HashTable
HashMap是线程不安全的,HashTable是线程安全的
HashMap的键值对允许为null,而HashTable的键值对不允许为null
public class Demo1 {
//map的使用
public static void test1() {
Map<String, Object> map = new HashMap<>();
//添加
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
//若key相同,则改变原来的value值
map.put("a", 4);
//删除
map.remove("b");
System.out.println(map.get("a"));
//如果key不存在,返回null
System.out.println(map.get("b"));
System.out.println(map.get("c"));
//判断指定key在不在map里
System.out.println(map.containsKey("a"));
//判断指定值在不在map里
System.out.println(map.containsValue(1));
}
//遍历方法
public static void test2() {
Map<String, Object> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
//第一种方式
Set<String> keys = map.keySet();
for(String key : keys) {
System.out.println(key+":"+map.get(key));
}
System.out.println("============================================");
//第二种方式
Set<Entry<String, Object>> entrys = map.entrySet();
for(Entry<String, Object> entry : entrys) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("============================================");
//第三种方式
map.forEach((k, v) -> System.out.println(k+":"+v));
}
public static void main(String[] args) {
//test1();
test2();
}
}
-
栈和队列
8.1 栈
先进后出
可以由数组实现,可以由链表实现
public class Demo3 {
public static void main(String[] args) {
//Stack栈 数组实现
Stack<String> stack = new Stack();
stack.push("hello");//压栈
System.out.println(stack.peek());//如果栈为空,抛出异常
System.out.println(stack.peek());//返回栈顶的元素,栈顶元素不弹出来
System.out.println(stack.pop());//返回栈顶的元素,栈顶元素弹出来,如果栈为空,抛出异常
System.out.println(stack.peek());
//栈 链表实现
LinkedList<String> list = new LinkedList<>();
list.push("zhou");
System.out.println(list.peek());
}
}
8.2 队列
先进先出
public class Demo4 {
public static void main(String[] args) {
// 队列
LinkedList<String> list = new LinkedList<>();
System.out.println(list.poll());//返回null
list.offer("a");//入列
list.offer("b");
list.offer("c");
System.out.println(list.peek());//返回队首的元素,并没有出列
System.out.println(list.poll());//返回队首的元素,出列
System.out.println(list);
//Queue 队列
Queue<String> queue = new LinkedList<>();
}
}