1.集合Set
在之前讲的内容中,List是有序的集合,Set是无序的(并且Set是由Map实现的)
有序和无序:
有序:取出的顺序和添加的顺序是一样的
2.集合Set的三个实现类:
HashSet,TreeSet,LinkedHashSet
3.HashSet:
add()方法:向集合中添加数据
remove()方法:删除集合中的某项
size()方法:返回集合中存放的数据的数量
HashSet set = new HashSet();
set.add("23");
System.out.println(set);
set.remove("123");
set.size();
set.add("23");
int size=set.size();
System.out.println(size);//输出1,Set里只有一个数 证明Set不能存储相同的数
set.add(256);
set.add(256);//注意!!同一类型的数据只能在set集合中存放一次
size = set.size();
System.out.println(size);//输出2,集合中只有两个数据
4.HashSet中可以存放null:
//Set可以存储null值
set.add(null);
size=set.size();//定义一个变量,来存储size()方法得到的集合中元素个数
System.out.println(size);.//原本有2个值,放入null后,集合中有3个值
for (Object item:set){
System.out.print(item+",");
}//遍历每一项,输出是无序的
5.遍历有三种方式:先序遍历,中序遍历,后序遍历
先序遍历
中序遍历:
后序遍历:
6.TreeSet
遍历有三种方式:先序遍历,中序遍历,后序遍历
在TreeSet中,采用的遍历方式是中序遍历
注意:不能往TreeSet中存放字符串类型String、null(原理:TreeSet对要传入的元素与集合中已有的元素进行比较,若相同则不能计入集合)
TreeSet tset = new TreeSet();
//存入数据
tset.add(2);
tset.add(200);
tset.add(3);
tset.add(88);
tset.add(45);
tset.add(72);
tset.add(1);
tset.add(99);
//tset.add("234"); 不能存字符串类型
//tset.add(null); 不能存null值,null值是不可以比较的对象,所以null不能往里放
for (Object item:tset){
System.out.print(item+",");
}
//利用迭代器输出的结果为:1,2,3,45,72,88,99,200,
最后输出结果为:1,2,3,45,72,88,99,200,(TreeSet输出是从小到大有序输出)
TrssSet 内部使用二叉树 内部节点是可以比较大小的
同一个TreeSet对象中存储的内容都应该是可以比较的(默认情况下不能存储不同类型的数据)
7.写一个Student类,类内部写一个选择器
class Student implements Comparable{
int score;
@Override
public int compareTo(Object o) {
if (o instanceof Student){
Student item=(Student)o;
if (this.score==item.score){
return 0;
}
return this.score> item.score?1:-1;
}
else {
//如果o对象不是Student就无法比较 这是程序运行时出现的特殊情况(这种特殊情况叫做异常情况)
//出现异常情况 我们的方法处理不了这种情况 就需要抛出一个异常对象,告知调用此方法的代码
throw new RuntimeException("传入对象不可比较");
}
}
8.对TreeSet传入对象时需要写一个选择器:
Comparator<Student> com =(a,b)->{
if (a.score==b.score){
return 0;
}
return a.score>b.score?1:-1;
};//
TreeSet<Student> ttset=new TreeSet<>(com);//com为上面写的选择器
Student stua=new Student();stua.score=89;
Student stub=new Student();stub.score=80;
Student stuc=new Student();stuc.score=99;
Student stud=new Student();stud.score=100;
ttset.add(stua);//89
ttset.add(stub);//80
ttset.add(stuc);//99
ttset.add(stud);//100
for (Student stu:ttset){
System.out.println(stu.score);
}
如果不放选择器,也没放进去指定的能比较的类型,则无法存入数据:
TreeSet tttset = new TreeSet();//要不就传入一个比较器,要不就放进去可比较的东西;
Student stuaa=new Student();stuaa.score=89;
tttset.add(stuaa);
System.out.println(tttset);
9.LinkedHashSet
//LinkedHashSet 是有序的集合Set
LinkedHashSet lhset =new LinkedHashSet();
10.Map
Map不属于Collection
Map存储的是键值对 键就是名字,值就是存储的对象
11.Map分为HashMap,TreeMap,LInkedHashMap,Hashtable,ConcurrentHashMap
12.HashMap
存入的方式可以理解为:(key,value)
HashMap的几种基本用法:
public static void main(String[] args) {
Map map=new HashMap();
map.put("A1","张三");
//可以通过存入的key获取存入的对象
Object obj =map.get("A1");
System.out.println(obj);
//通过key删除键值对
Object rem_obj=map.remove("A1");//存储了要删除的值
System.out.println("删除的值为:"+rem_obj);//输出删除的值
map.containsKey("A1");//是否包含key
map.containsValue("张三");//是否包含value值
map.keySet();//获取所有的key
map.values();//获取所有的value
Collection con = map.values();
System.out.println(con);//输出[],集合中存入的值被remove()方法删除
map.put(null,null);//只能放入一个key是null,不能放入多个重复的key
map.put("A1",null);
map.put("A1","张三");
System.out.println(map);//{null=null, A1=张三}
}
HashMap 底层实现 数组加链表
HashMap 的数组默认容量为16,每次扩容2倍
扩容阈值: 0.75 一个链达到8就要对该链进行树化
一支树上的元素低于6个,这个树就会退化成链 //最小树化容量阈值 64(数组不少于64项)
如果数组长度没有达到64,优先扩容,达到64之后且一个链达到8就会树化
13.TreeMap
//TreeSet的底层实现是TreeMap(TreeMap的key不能是null值)
//HashSet的底层实现是HashMap
//key应该是可比较的
14.HashTable
Hashtable ht =new Hashtable();
ht.put("t1","张三");
//Hashtable key和value都不能使用null值
//Hashtable 是线程安全的
15.LinkedHashMap
LinkedHashMap也是有序的
16.ConcurrentHashMap
是线程安全的(正常线程安全后效率会降低,但ConcurrentHashMap不受影响),效率较高
17.泛型 广泛的数据类型 是用来确保类型安全的一种途径
定义:在类或方法上定义泛型
public class EasyGenericity<J,M,N,Y,Easy> {//定义泛型
private M m;
public void test(M m,N n){}
public <E> E test(E e){
//返回的类型和传入的类型是同一种或是相同的
return e;
}
public static <J extends List> J testA(J j){//这里的J是新建的J,并不是定义类时的J
//定义上限为List
return j;
}
public static <A> void testAA(List<? super A> a,A p) {
// 方法实现...
}
}
class A{}
class B extends A{}
class C extends B{}
主函数如下:
public static void main(String[] args) {
//类型安全
List list = new ArrayList();
list.add("123");
list.add(new Object());
for (Object object:list){
//在类型转换时,没有明确对象的数据类型进行强制类型转换,会抛出ClassCaseExcpetion异常(类型转换异常)
//类型不安全
String str = (String)object;
System.out.println(str);
}
List<String> lista = new ArrayList<>();//在编译的时候起作用
lista.add("123");
System.out.println(lista);
Map<String,Object> map = new HashMap<>();
System.out.println(map);
testA(new ArrayList());
//testA(new HashSet<>());
List<A> list1=new ArrayList<>();
List<B> list2=new ArrayList<>();
List<C> list3=new ArrayList<>();
testAA(list2,new B());//key传list3不行,因为下限传进去了B
}