集合学习
集合框架
- Collection接口:单列集合
- list接口:有序(存和取的顺序一致),可重复(有索引)
- ArrayList、LinkedLashSet、TreeSet
- Set接口:无序,不可重复(无索引)
- HashSet、LinkedHashSet(有序,不重复)、TreeSet(可排序)
- list接口:有序(存和取的顺序一致),可重复(有索引)
- Map接口:双列集合,键值对
- HashMap(存取不一致)、LinkedHashMap(存取一致)、TreeMap、Hashtable、Properties
Collection集合的基本功能
c.remove(); 删除指定元素
c.clear(); 清空集合
c.isEmpty(“b”); 判断是否包含b
c.size(); 获取元素个数b
c.contains(b) 判断是否包含b;
contains和remove方法底层是equal方法,默认比较的时地址值,去除自定义对象元素的重复值时,需要重写equal方法;
带All的功能
boolean addAll(Collection c) 把c看作一个对象添加到c1中
boolean removeAll(Collection c) 删除c1与c2的交集;
boolean containsAll(Collection c) 判断c1是否包含c2;
boolean retainAll(Collection c) 取交集
迭代器的使用
Collection c = new ArrayList();
c.add("a");
c.add("b");
c.add("c");
c.add("d");
Iterator it = c.iterator(); //获取迭代器的引用
while(it.hasNext()) { //集合中的迭代方法(遍历)
System.out.println(it.next());
}
List
list特有的方法:
List集合的特有功能概述
- void add(int index,E element) 通过索引添加
- remove(int index) 通过索引删除
- get(int index) 获取索引为index的值
- set(int index,E element) 将指定位置的元素修改
list特有的迭代器(ListIterator)
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
ListIterator listIterator = list.listIterator(); //获取迭代器(list特有的迭代器)
while (listIterator.hasNext()){
String str = (String) listIterator.next(); //向下转型
if(str.equals("d")) {
listIterator.add("游戏");
/*Iterator iterator = list.iterator(); //这种会发生并发修改异常ConcurrentModificationException
while (iterator.hasNext()) {
String str = (String)iterator.next();
if(str.equals("a")){
list.add("优秀");*/
}
}
}
Vector
数据结构之数组和链表
- A:数组
- 查询快修改也快
- 增删慢
- B:链表
- 查询慢,修改也慢
- 增删快
A:List的三个子类的特点
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
Vector和ArrayList
区别:
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
共同点:都是数组实现的
ArrayList和LinkedList
区别:
ArrayList底层是数组结果,查询和修改快
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的
List有三个儿子,我们到底使用谁呢?
查询多用ArrayList
增删多用LinkedList
如果都多ArrayList
LinkedList的特有功能
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
public E get(int index);//通过索引获取
栈和队列
- 栈
先进后出 - 队列
先进先出
泛型概述和基本使用
- A:泛型概述
- B:泛型好处
- 提高安全性(将运行期的错误转换到编译期)
- 省去强转的麻烦
- C:泛型基本使用
- <>中放的必须是引用数据类型
- D:泛型使用注意事项
- 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)
三种循环能否实现删除?
public class Demo1_Foreach {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("张三");
arrayList.add("张三");
arrayList.add("李四");
arrayList.add("王五");
arrayList.add("赵云");
/*普通for循环
for (int i = 0; i < arrayList.size(); i++) {
if("张三".equals(arrayList.get(i))){
arrayList.remove(i--);
}
}*/
/* Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
if(str.equals("赵云")){
//arrayList.remove("赵云"); //ConcurrentModificationException并发修改异常
iterator.remove();
}
}*/
/*for(Iterator<String> iterator = arrayList.iterator(); iterator.hasNext();){
if(iterator.next().equals("张三")){
iterator.remove();
}
}*/
//增强for循环 结论:增强for循环不能删除,只能遍历
for (String str : arrayList
) {
System.out.println(str);
if (str.equals("赵云")) {
arrayList.remove("赵云");//ConcurrentModificationException并发修改异常
}
}
}}
结论:增强for循环不能删除,迭代器可以删除,普通for循环通过get()方法可以删除
集合<=>数组
集合转数组:
ArraryList<String> arrayList = new ArrayList();
arrayList.toArray(new String[0])
数组转集合:
int[] arr = {1,2,3,4,5};
List<int[]> list = Arrays.asList(arr);
集合嵌套集合
ArrayList<ArrayList<Person>> list = new ArrayList<>();
ArrayList<Person> first = new ArrayList<>();
first.add(new Person("张三",23));
first.add(new Person("李四",24));
ArrayList<Person> second = new ArrayList<>();
first.add(new Person("王五",25));
first.add(new Person("赵六",26));
list.add(first);
list.add(second);
for (ArrayList<Person> p :list
) {
for (Person pe: p
) {
System.out.println(pe);
}
}
}
set
hashset
没有特有的方法;
- hashset存储字符串并遍历
HashSet<String> hs = new HashSet<>();
boolean a1 = hs.add("a");
boolean a2 = hs.add("a"); //如果重复,返回的boolean值为false
/*for (String str :hs
) {
System.out.println(str);
}*/
Iterator<String> iterator = hs.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//不可以用普通for循环遍历,可以用foreach和迭代器(只要能用foreach的都可以用迭代器)
hashset如何保证元素唯一
HashSet集合的特点是元素无序和不重复 。
首先,HashSet的底层数据结构是哈希表。哈希表就是存储一系列哈希值的表,而哈希值是由对象的hashCode()方法生成的。
确保元素唯一性的两个方法,**hashCode()和equals()**方法。
当调用add()方法向集合中存入对象的时候,先比较此对象与原有对象的哈希值有没有一样的,如果都不一样就直接存入;如果有与之相同的哈希值,则要继续比较这两个对象是否为同一个对象,此时就要调用对象的equals()方法了。
总之,只有HashCode的至相同时,才会调用equals()方法。
在判断元素是否存在和删除一个元素的时候,也是这个过程。
LinkedHashSet
原理:
- 底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
- 因为是HashSet的子类,所以也是保证元素唯一,与HashSet的原理一样
TreeSet
内含比较器comparator
TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一性
使用TreeSet时,实体类必需实现Comparable接口;
当compareTo方法返回0的时候集合中只有一个元素;
当compareTo方法返回正数的时候集合怎么存就怎么取;
当compareTo方法返回负数的时候集合倒序取出
//按照姓名排序
public int compareTo(Person o) {
int i = this.name.compareTo(o.name);
return i == 0? o.age-this.age:i;
}
/*按照年龄排序
public int compareTo(Person o) {
int num = o.age - this.age;
return num == 0 ? this.name.compareTo(o.name):num;
}*/
TreeSet中的比较器排序
public static void main(String[] args) {
//demo();
//demo2();
//demo3();
TreeSet<String> ts = new TreeSet<>(new myComparable());//myComparable c = new mycomparable;
ts.add("aaaaa");
ts.add("abcx");
ts.add("sss");
ts.add("as");
ts.add("a");
System.out.println(ts);
}
}
class myComparable implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
int num = o1.length() - o2.length(); //比较长度(住)
return num ==0 ?o1.compareTo(o2):num;//比较内容(次)
}
### TreeSet原理
- 1.特点
- TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
- 2.使用方式
- a.自然顺序(Comparable)
- TreeSet类的add()方法中会把存入的对象提升为Comparable类型
- 调用对象的compareTo()方法和集合中的对象比较
- 根据compareTo()方法返回的结果进行存储
- b.比较器顺序(Comparator)
- 创建TreeSet的时候可以制定 一个Comparator
- 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
- add()方法内部会自动调用Comparator接口中compare()方法排序
- 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
- c.两种方式的区别
- TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
- TreeSet如果传入Comparator, 就优先按照Comparator
- a.自然顺序(Comparable)
Map
Map集合的概述和特点
- A:Map接口概述
- 查看API可以知道:
- 将键映射到值的对象
- 一个映射不能包含重复的键
- 每个键最多只能映射到一个值
- 查看API可以知道:
- B:Map接口和Collection接口的不同
- Map是双列的,Collection是单列的
- Map的键唯一,Collection的子体系Set是唯一的
- Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
Map集合的功能概述
- a:添加功能
* V put(K key,V value):添加元素。
* 如果键是第一次存储,就直接存储元素,返回null
* 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值- b:删除功能
- void clear():移除所有的键值对元素
- V remove(Object key):根据键删除键值对元素,并把值返回
- c:判断功能
- boolean containsKey(Object key):判断集合是否包含指定的键
- boolean containsValue(Object value):判断集合是否包含指定的值
- boolean isEmpty():判断集合是否为空
- d:获取功能
- Set<Map.Entry<K,V>> entrySet():
- V get(Object key):根据键获取值
- Set keySet():获取集合中所有键的集合
- Collection values():获取集合中所有值的集合
- e:长度功能
- int size():返回集合中的键值对的个数
- b:删除功能
HashTable和HashMap的区别
相同点:双列集合,底层都是哈希算法
不同点:
- Hashtable线程安全,效率低,jdk1.0
HashMap线程不安全,效率高,jdk1.2 - Hashtable不可以存储null值和null键
HashMap可以存储null值和null键
Conllections工具类常用方法
public static <T> void sort(List<T> list) //将集合排序
public static <T> int binarySearch(List<?> list,T key) //输入集合中的值,得到该值的位置
public static <T> T max(Collection<?> coll) // 获取最大值
public static void reverse(List<?> list) //反转
public static void shuffle(List<?> list) //随机置换
总结
- Collection
- List(存取有序,有索引,可以重复)
- ArrayList
底层是数组,线程不安全,效率高,查询快,增删慢; - LinkedList
底层是链表实现的,线程不安全,效率高,增删快,查询慢; - Vertor
底层是数组,线程安全,增删改查都慢;
- ArrayList
- set(存取无序,无索引,不可以重复)
- HashSet
底层是哈希算法,存取无序,不可重复 - LinkedHashSet
底层是链表实现的,存取有序,不可重复(set集合中唯一一个存取有序的集合) - TreeSet
底层是二叉树,有比较器comparator,可以自定义排序输出;
- HashSet
- List(存取有序,有索引,可以重复)
- Map
- HashMap
底层是哈希算法,针对键,键值对双列集合
存入的键和值可以为null - LInkedHashMap
底层是链表,针对键 - HashTable
键值对双列集合
存入的值和键不能为null - TreeMap
底层是二叉树,针对键
- HashMap