泛型
java泛型设计原则:保证编译时不出错,运行时就不会出现ClassCastException
1、泛型类
在类上定义的泛型,在方法中也可使用
2、泛型接口
interface DemoInter<T>{
void show(T t);
}
class Demo3Impl1 implements DemoInter<String>{
@Override
public void show(String t) {
// TODO Auto-generated method stub
}
}
class Demo3Impl2<T> implements DemoInter<T>{
@Override
public void show(T t) {
// TODO Auto-generated method stub
}
}
public class Demo3 {
public static void main(String[] args) {
DemoInter<String> d1=new Demo3Impl1();
DemoInter<String> d2=new Demo3Impl2<>();
}
}
3、泛型方法
♥泛型方法所在类不一定是泛型类
√ 方法的返回类型前加
public static <T> void print(T[] arr){
for(int i = 0)
System.out.println(arr[i]);
}
♥泛型使用必须为引用类型Integer,String,Double等
不能用8种基本数据类型
//泛型类
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;
}
@Override
public String toString() {
return "TestObj [data=" + data + ", name=" + name + "]";
}
}
public class _demo2 {
//输出任意数据类型的数组元素
public static<T> void showData(T[] a) {
for(int i = 0;i < a.length ;i++) {
System.out.println(a[i]);
}
System.out.println("-------------");
for(T t : a) {
System.out.println(t);
}
}
public static void test3() {
Integer[] num = {1,2,3};//必须用引用类型
showData(num);
}
public static void test() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(8);//确定范型后其中不可输入非下层数据类型的值
}
public static void test2() {
TestObj<String> stu = new TestObj<>();
stu.setName("zhangsna");
stu.setData("6790");
System.out.println(stu);
TestObj<Float> emp = new TestObj<>();
emp.setData(10000.34F);
emp.setName("校长");
System.out.println(emp);
}
public static void main(String[] args) {
test();
}
}
4、泛型的使用
♥<>中类型没有继承关系,本类只能用本类
♥若想使用请换为通配符?
通配符:?表示任意数据类型
5、通配符上限:<? extends Animal>
6、通配符的下限<? super Animal>
public class Demo4 {
public static void show(List<?> list) {
for (Object obj:list) {
System.out.println(obj);
}
}
// public static void show(List<Object> 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<String> list = new ArrayList<>();
// List<Object> list = new ArrayList<>();
// List<String> list = new ArrayList<>();
//<>中类型没有继承关系,本类只能用本类
//若想使用请换为通配符?
list.add("abc");
list.add("sdf");
list.add("jian");
show(list);
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(7);
test1(list1);
// test2(list1);//报错
}
// public <?> void t(List<?> list) {
// }//第一个?报错:Syntax error on token "?", Identifier expected语法错误,需要标识符
}
//class A<>{}//报错:Syntax error on token "?", Identifier expected语法错误,需要标识符
7、错误使用
1》class A<?>{}//报错:Syntax error on token “?”, Identifier expected语法错误,需要标识符
2》public <?> void t(List<?> list) {}//第一个?处报错,报错信息与上句一直
3》List<?> list = new ArrayList<?>();//第二个?处报错List<?> list = new ArrayList<>();正确
Stream
Stream:与IO流无关
1、流式思想:
像生产流水线一样,一个操作接着一个操作
使流操作集合更高效
2、stream特性:
1》stream 不存储数据
2》stream不改变原数据
3》stream的延迟执行特征
3.使用Stream流的步骤:
数据源→转换成流→操作1→操作2→……
4.数据源(source):
可以是集合、数组等。
5.获取流:
// List
// 数组
6.常用方法
Stream只能被使用一次,如果还想使用,必须重新获取流。
如果不重新获取,会得到异常:
异常类型java.lang.IllegalStateException
提示消息:stream has already been operated upon or closed
1>.filter() 方法用于通过设置的条件过滤出元素
2>.map() 方法用于映射每个元素到对应的结果
3>.limit() 方法用于获取指定数量的流
4>.跳过前n个stream.skip()
5>.流的连接Stream.concat(stream1,stream2)
6>.回数量count()
7>.可以把流转换为 List 类型:collect(Collectors.toList());
8>.求和的方法reduce(0, (x, y) -> x + y)或者reduce(1,(x,y)->x*y)
9>.去重distinct()
10>.排序:sorted()
11>forEach()终结方法
public class Demo5 {
public static void test1() {
List<String> listStr = new ArrayList<>();
listStr.add("hello");
listStr.add("admin");
Integer[] num = {1,2,3,4};
Stream<String> streamStr = listStr.stream();
Stream<Integer> streamInt = Stream.of(num);
Stream.concat(streamStr,streamInt).forEach(e->System.out.println(e));
//concat连接两个流
// streamInt.forEach(e->System.out.println(e));
//streamInt.forEach(e->System.out.println(e));
//终结性方法(返回类型不是流),不可多次使用流运行出现java.lang.IllegalStateException
}
public static void test2() {
Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9);
// Stream<Integer> numStream = stream.filter(e -> e%2!=0);
// numStream.forEach(e->System.out.println(e));
Stream<Integer> numStream = stream.filter(e ->{
System.out.println("------------");
return e%2!=0;
});
System.out.println("------------8-------");
numStream.forEach(e->System.out.println(e));//延迟执行
stream = Stream.of(1,2,3,4);
stream.map(e->e*e).forEach(e->System.out.println(e));
stream = Stream.of(1,2,3,4);
stream.limit(3).forEach(e->System.out.println(e));//限制输出3个
stream = Stream.of(1,2,3,4);
stream.skip(3).forEach(e->System.out.println(e));//跳过3个
}
public static void test3() {
Stream<Integer> stream = Stream.of(1,2,3,4);
System.out.println(stream.count());
//返回一个集合
stream = Stream.of(1,2,3,4);
List<Integer> list = stream.collect(Collectors.toList());
System.out.println(list);
stream = Stream.of(1,2,3,4);
System.out.println(stream.reduce(0,(x,y)->x+y));
stream = Stream.of(1,2,3,4,1,4,3);
stream.distinct().forEach(e->System.out.println(e));
System.out.println("---------排序--------------");
stream = Stream.of(1,2,3,4,1,4,3);
stream.sorted().forEach(e->System.out.print(e+" "));
// stream.sorted((x,y)->y-x).forEach(e->System.out.print(e+" "));//从大到小,自己重写compareTo方法
}
public static void main(String[] args) {
test2();
}
}
下面有一组练习题以及答案
练习:
1.//有如下整数1,-2,-3,4,-5,使用Stream取元素绝对值并打印
2.给定一个数字列表,如何返回一个由每个数的平方构成的列表,给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】。
3.有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,使用Stream将以郭字开头的元素存入新集合
4.已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、武眠风、冯默风、罗玉风},
使用Stream
《1、取出前2个元素并在控制台打印输出。
《2、取出后2个元素并在控制台打印输出。
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)
);
6.找出2011年发生的所有交易, 并按交易额排序(从低到高)
class Transaction {
private int year; //交易时间
private int value; //交易额
方法。。。。
List 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)
);
答案:
public class Demo6test {
//1\有如下整数1,-2,-3,4,-5,使用Stream取元素绝对值并打印
public static void test1() {
Stream<Integer> stream = Stream.of(1,-2,-3,4,-5);
// stream.sorted((x,y)->Math.abs(x)-Math.abs(y)).forEach(e->System.out.println(Math.abs(e)));
// stream.forEach(e->System.out.println(Math.abs(e)));
stream.map(e->Math.abs(e)).forEach(e->System.out.println(e));
}
//2\给定一个数字列表,如何返回一个由每个数的平方构成的列表
public static void test2() {
Stream<Integer> stream = Stream.of(1,2,3,4,5);
// stream.forEach(e->System.out.println(e*e));
stream.map(e->e*e).forEach(System.out::println);
}
//3.有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,使用Stream将以郭字开头的元素存入新集合
public static void test3() {
Stream<String> stream = Stream.of("黄药师","冯蘅","郭靖","黄蓉","郭芙","郭襄","郭破虏","hajn郭7");
> 这里是引用
// stream.filter(e->e.startsWith("郭")).forEach(e->System.out.println(e));
System.out.println(stream.filter(e->e.startsWith("郭")).collect(Collectors.toList()));//filter可以将所有返回()内true的收集起来返回一个stream
}
//4.已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、武眠风、冯默风、罗玉风},
public static void test4() {
List<String> list = new ArrayList<>();
list.add("陈玄风");
list.add("梅超风");
list.add("陆乘风");
list.add("曲灵风");
list.add("武眠风");
list.add("冯默风");
list.add("罗玉凤");
Stream<String> stream = list.stream();
stream.limit(2).forEach(e->System.out.println(e));
stream = list.stream();
// stream.skip(5).forEach(e->System.out.println(e));
stream.skip(list.size()-2).forEach(e->System.out.println(e));
}
//5.怎样用 map 和 reduce 方法数一数流中有多少个Employee
public static void test5() {
List<Employee> emps = Arrays.asList(
new Employee(101, "张三", 18),
new Employee(102, "李四", 59),
new Employee(103, "王五", 28),
new Employee(104, "赵六", 8),
new Employee(105, "田七", 38)
);
Stream<Employee> emp =emps.stream();
// System.out.println(emp.count());
System.out.println(emp.map(e->1).reduce(0,(x,y)->x+y));
}
//6.找出2011年发生的所有交易, 并按交易额排序(从低到高)
public static void test6() {
List<Transaction> transaction = Arrays.asList(
new Transaction(2011,300),
new Transaction(2012,1000),
new Transaction(2011,400),
new Transaction(2012,7100),
new Transaction(2011,200),
new Transaction(2012,700),
new Transaction(2012,950)
);
Stream<Transaction> trans = transaction.stream();
trans.filter(e->
e.getYear()==2011
).sorted((t1,t2)->t1.getValue()-t2.getValue()).forEach(System.out::println);
}
public static void main(String[] args) {
test3();
}
}
public class Employee {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
public Employee(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
public class Transaction {
private int year;
private int value;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return "Transaction [year=" + year + ", value=" + value + "]";
}
public Transaction(int year, int value) {
super();
this.year = year;
this.value = value;
}
}
List、Set、Map、LinkList
1、List集合的实现类
LinkedList和Vector
LinkedList和ArrayList都是线程不安全的的
Vector是线程安全的
2、Set集合
不重复:先判断hashCode();相同,还有判断equals()方法,只有返回true才表示同一对象
HashSet和TreeSet
HashSet基于HashMap的实现,HashSet的元素是map中的key。
TreeSet的元素必须是有排序规则的对象,否则会运行时异常
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不重写hashCode(),equals(Object obj)方法,会出现重复值,有多个张三
}
public static void main(String[] args) {
test2();
}
}
public class Emp{
private String id;
@Override
public 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;
}
@Override
public 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;
}
private String name;
public Emp(){
}
public Emp(String name) {
this.setName(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Emp [name=" + name + "]";
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
3、Map集合
HashMap
Map
k-v
HashMap与HashTable区别
1>HashTable线程安全
2>HashMap的key/value可为null,
HashTable键值都不可以为null,会出现空指针异常
package Demo0807;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
Map<String, Object> map = new Hashtable<>();
map.put("k","njn");
test3();
}
public static void test1() {
Map<String, Object> map = new HashMap<>();
// 添加元素
map.put("a", 97);
map.put("b", 98);
map.put("b", 998);// key值相同,修改了value
map.put("c", 99);
map.remove("c");
System.out.println(map.get("a"));
System.out.println(map.get("b"));
System.out.println(map.get("c"));// 获取已删除或不存在键值对,返回为null
}
public static void test2() {
Map<String, Object> stu = new HashMap<>();
stu.put("id","200090001");
stu.put("name", "admin");
stu.put("phone", "1234544");
stu.put("age", 18);
stu.put("adress","光谷软件园");
System.out.println(stu.containsKey("name"));
System.out.println(stu.containsValue("admin"));
}
public static void test3() {
Map<String, Object> stu = new HashMap<>();
stu.put("id","200090001");
stu.put("name", "admin");
stu.put("phone", "1234544");
stu.put("age", 18);
stu.put("adress","光谷软件园");
//遍历方式一
System.out.println("-----------1----------");
Set<String> key = stu.keySet();
for (String key1:key) {
System.out.println(key1+":"+stu.get(key1));
}
//第二种
System.out.println("-------------2-----------");
Set<Entry<String, Object>> stua = stu.entrySet();
for(Entry<String, Object> entry : stua) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
//第三种
System.out.println("-----------3------------");
stu.forEach((k,v)->System.out.println(k+":"+v));
System.out.println("-----------value-----------");
System.out.println(stu.values());
Collection<Object> collection = stu.values();
for(Object obj : collection) {
System.out.println(obj);
}
}
}
练习:接受键盘输入一个字符串,统计字符的个数 vserererew
public class Demo2test {
public static void main(String[] args) {
System.out.println("请输入一个字符串");
Scanner sc = new Scanner(System.in);
String str = sc.next();
Map<Character, Integer> map = new HashMap<>();
// char[] array = str.toCharArray();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(map.containsKey(c)) {
int count = map.get(c);
map.put(c,++count);
}else {
map.put(c,1);
}
}
map.forEach((k,v)->System.out.println(k+":"+v));
}
}