1c 集合.txt
UP 返回
1.Collection接口 (集合,定义的是所有单列集合中共性的方法,没有带索引的方法)
集合只能存储对象
2.List接口(继承于Collection):
1.有序的集合(存储和取出元素顺序相同)
2.允许存储重复的元素
3.有索引,可以使用普通的for循环遍历
子类有Vector,ArrayList,LinkedList
Set接口(继承于Collection):
1.不允许存储重复元素
2.没有索引,不能使用普通的for循环遍历
子类有TreeSet,HashSet,两者是无序集合(HashSet有子类LinkedHashSet,是有序集合)
3.Collection常用功能
public boolean add(E e);//添加对象
public void clear();//清空集合
public boolean remove(E e);//删除集合中该对象
public boolean contains(E e);//判断集合中是否包含该对象
public boolean isEmpty();//判断集合是否为空
public int size();//集合元素个数
public Object[] toArray();//把集合元素存入数组
4.Iterator接口(迭代器)
boolean hasNext();//判断集合中有没有下一个元素
E next();//取出集合中下一个元素
获取Iterator实现类的方法:Collection中有一个方法Iterator<E> iterator(),返回此集合对应的迭代器
Iterator<String> it=coll.iterator();
while(it.hasNext){ //使用while循环
String e=it.next();
System.out.println(e);
}
for(Iterator<String> it=coll.iterator();it.hasNext()){ //使用for循环
String e=it.next();
System.out.println(e);
}
foreach语句(增强for)内部即是通过迭代器实现
5.泛型
5.1 集合不使用泛型的话,默认的类型是Object 。使用泛型的好处是:1.避免了类型转换的麻烦(存储什么类型取出就是什么类型) 2.把运行期异常提升到了编译期;弊端是:泛型是什么类型,就只能存储什么类型 =============(未理解这句话的含义,待定)
泛型类的创建和使用:
public class GenericClass<E>{
private E name;
public E getName(){
return name;
}
public void setName(E name){
this.name=name;
}
}
GenericClass<Integer> gc1=new GenericClass<>();
gc1.setName(1);
Integer name=gc1.getName();
System.out.println(name);
GenericClass<String> gc2=new GenericClass<>();
gc2.setName("小明");
String name1=gc3.getName();
System.out.println(name);
5.2 定义含有泛型的方法:
public class GenericMethod{
public <M> void method(M m){ //泛型写在函数的修饰符和返回类型之间,<M>不可删
System.out.println(m);
}
}
5.3 定义含有泛型的接口:
public interface GenericInterface<I>{
public abstract void method(I i);
}
public class GenericInterfaceImpl1 implements GenericInterface<String>{ //1.实现类指定泛型的类型
@Override
public void method(String s){ //对应的泛型方法自动变为设定的类型
}
}
public class GenericInterfaceImpl2<I> implements GenericInterface<I>{ //2.实现类仍然使用泛型,创建对象的时候再指定类型
@Override
public void method(I s){ //对应的泛型方法自动变为设定的类型
}
}
5.4 泛型通配符:不知道使用什么类型来接收的时候,可以使用?表示未知通配符,此时只能接收数据,而不能往该集合中存储数据
public static void printArray(ArrayList<?> list){ //通配符作为参数
Iterator<?> it=list.iterator();
whiel(it.hasNext()){
Object o=if.next(); //此时返回的只能是Object
System.out.println(o);
}
}
定义的时候不可用,比如不可以写:ArrayList<?> list=new ArrayList<?>();,只能在参数传递的时候用
5.5 受限泛型(只要在阅读java源码时能看懂即可)
泛型的上限限定:? extends E 代表使用的泛型只能是E和E的子类 :public static void getElement1(Collection<? extends Number> coll){} //此处的?只能是Number或者其子类
泛型的下限限定:? super E 代表使用的泛型只能是E和E的父类 :public static void getElement2(Collection<? super Number> coll){} //此处的?只能是Number或者其父类
6.红黑树(趋近于平衡树,查询叶子节点最大次数和最小次数不能超过2倍)
二叉树;排序树/查找树;平衡树;红黑树
红黑树:
1 趋近于平衡树,查询叶子节点最大次数和最小次数不能超过2倍
2 结点可以是红色的或者黑色的
3 根节点是黑色的
4 叶子节点(空节点)是黑色的
5 每个红色结点的子节点都是黑色
6 任何一个结点到其每一个叶子节点的所有路径上黑色节点数相同
7.List集合
List<String> list=new ArrayList<>();
ArrayList是一个数组实现,查询快,增删慢,是多线程的(不同步)。增加元素时他的底层实际是重新创建一个新的数组,再将原数组复制过来(适用于查询较多的)
public void add(int index ,E element);
public E get(int index);
public E remove(int index);
public E set(int index ,E element);
LinkedList是一个双向链表实现,查询慢(但是首尾元素的查询很快),增删快,也是多线程。里面包含了大量操作首尾元素的方法(此类不可使用多态定义变量,即只能写LinkedList<String> linked=new LinkedList<>();,不可用List<String> linked...)
public void addFirst(E e);
public void addLast(E e);
public void push(E e); //等价于addFirst(E e)
public E getFirst();
public E getLast();
public E removeFirst(); //返回的是被移除的元素
public E removeLast();
public E pop(); //等价于removeFirst()
public boolean isEmpty();
Vector 对所有单列集合进行了包装,底层也是一个数组。是同步的(单线程,故速度慢,1.0版本出现,1.2版本之后就被替代了)
8.Set接口(不包含重复元素的collection,且最多包含一个null,接口中无索引)
HashSet 哈希表结构,不保证set的迭代顺序,查询速度很快(使用迭代器或者增强for遍历)
jdk1.8之前,哈希表=数组+链表;1.8以后,哈希表=数组+红黑树(提高查询速度。链表长度超过8位就转为红黑树)
在向HashSet中添加元素时,add方法首先会计算hashCode(),如果没有则添加,如果有相等的,说明有冲突,再做equals比较两个元素是否相同,不同再存入。
hash值:系统随机给出的一个十进制整数,是对象的逻辑地址值:
public native int hashCode(); //获取hashcode,native代表该方法调用的是本地操作系统的方法。toString方法使用的也是这个hashcode
String类重写了hashCode(),故相同的字符串返回的哈希值是一样的。特别的:"重地"和"通话"两个字符串的哈希值一样,巧合
在HashSet中存放自定义类型的元素时,需要重写hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中对象唯一(IDEA中Alt+Insert可以自动添加方法代码)
LinkedHashSet 具有可预知迭代顺序的Set接口的哈希表和链表实现(内部有一个双重链表专门维护存入的元素顺序)
可变参数:
1.一个方法的参数列表,只能有一个可变参数
2.如果方法有多个参数,可变参数必须在最后
public static void method(String a,double b,int d,int...a){ }
特殊写法: public static void method(Object...obj){ } //可以接受任意参数
9.Collections工具类
public static <T> boolean addAll( Collection<T> c ,T... elements );//往集合中添加一些元素
public static void shuffle( List<?> list );//打乱集合顺序
public static <T> void sort( List<T> list );//元素按默认排序;排序自定义的类需要实现Comparable<自定义类名>,重写compareTo方法(返回this-参数表示升序),规定排序规则
public static <T> void sort( List<T> list ,Comparator<? super T> );//元素按指定规则排序
Comparator和Comparable的区别:
Comparator:自己(this)和别人(参数)比较,自己需要实现Comparable接口,重写比较规则compareTo方法
Comparable:相当于找一个第三方的裁判,比较两者
Collections.sort(list01, new Comparator<Integer>(){
@Override
public int compare(Integer o1,Integer o2){ //如果是自定义的类型也需要重写该方法
//return o1-o2; //升序
return o2-o1; //降序
}
});
10.Map集合 java.util.HashMap<k,v> implements Map<k,v>
HashMap 哈希表结构(参HashSet);无序集合;不同步(多线程,速度快) 【事实上HashMap在add时会自动对key值进行排序,所以有时可以通过此特性实现自动排序的功能,参视频 \2019年4月黑马程序员教程\01-黑马IDEA版本Java基础+就业课程\1.基础班\1-8 File类与IO流\第7节 缓冲流\08_练习_对文本的内容进行排序】
HashSet的底层就是一个HashMap的实现,但是只使用了key,所以HashSet不允许相同元素同时存在
LinkedHashMap 哈希表+链表;有序集合(链表可以保证)
10.1 Map常用方法
public V put(K key,V value);//存储键值对,key不存在时返回null,key不存在时新的value覆盖旧的值,同时返回旧的值
public V remove(Object key);//删除指定的键值对;key存在返回被删除的值,不存在返回null
public V get(Object key);//获取key的value
boolean containsKey(Object key);//是否包含key
keySet();//取出集合key的集合:Set<String> set=map.keySet(); Iterator<String> it=set.iterator();//再遍历循环(通过get(Object key)获得value)
10.2 Map有一个内部嵌套接口Map.Entry<K,V>,映射项(键-值对)
Map一旦创建,Entry对象即被创建,用来记录键值对:
Set<Map.Entry<String,String>> set=map.entrySet();//entrySet()方法可以得到Entry集合
Iterator it=set.iterator();//遍历
当然上面的set集合也是可以直接用增强for来遍历的:
for(Map.Entry<String,String> entry:set){
String key=entry.getKey();
tring value=entry.getValue();//Entry的两个get方法
10.3 HashMap存储自定义类型的键值时,作为key的元素必须重写hashCode()和equals方法,以保证key唯一(不重写的话同样的对象基本会被当成不同的来添加进入map)
10.4 Hashtable<K,V> 也是一个哈希表实现,区别就是该类只允许非null对象作为键值(开始于1.0,另外两个是1.2开始。之前所有的集合都可以存入null);是线程安全的(同步,单线程,速度慢)
HashTable和Vector现在都不常用了(先进的HashMap,ArrayList所替代),但是HashTable的子类Properties依然在使用(properties是一个唯一和IO流相结合的集合)
11.JDK9对集合的更新
11.1 jdk9添加了几种集合工厂方法,更方便创建少量元素的集合和map
static <E> List<E> of (E... elements);//List,Set,Map接口里增加了一个静态的方法of,可以给集合一次性添加多个元素(集合元素已确定的情况下)。只适用于这三个接口,不包括实现类;返回的是一个不可改变的集合(无法再使用add put方法了,会抛出异常。同时set和map在调用of时不可有重复元素):
List<String> list=List.of("a","b","a","d","e");
list.add("w");//UnsupportedOperationException
Set<String> set=Set.of("a","b","a","d","e");//IllegalArgumentException
Set<String> set=Set.of("a","b","c","d","e");
Map<String,Integer> map=Map.of("张三",18,"李四",19,"王五",20);
map.put("赵四",30);//报错
DOWN 返回