集合
1.容器用来储存数据的数据结构。 变量时最小的容器--只能存一个数据。
2. Collection--集合的顶级父接口。java.util.Collection,一组Collection代表一组对象。集合中只能存对象(实际上存的是对象的引用)。
1. Collection没有任何的实现类。其下有两个子接口List和Set。
1. List(JDK1.2才出现)的实现类
1. ArrayList--底层基于数组,有序,可重复集。
1. 默认数组的大小为10,每次扩容为1.5倍(扩容的实现为位运算)。
2. 内存空间是连续的,可以基于下标进行操作集合。查找效率高,插入和删除效率低。
3. 线程是不安全的。
2. LinkedList--底层基于链表实现。
1. 内存空间不连续,基于节点储存元素(first data last),查询慢,插入和删除效率高。
2. 线程不安全。
3. vector:JDK1.0就有了,JDK1.2开始实现List接口,是最早的集合类之一。基于数组实现,默认数组的大小为10,扩容时,每次扩大一倍(基于三目运算)。
1. 内存空间连续。有序,可重复集。查询效率高,插入和删除效率慢。
2. 线程安全。
4. Stack:栈。遵循LILO(先进后出)原则。
1. 基于Vector实现,线程安全。
List(JDK1.2才出现)
list有序的,按照元素存入的顺序排序(有下标,从0开始)。可重复的。
提供了一些基于下标的操作
E set(int index, E element) 用指定元素替换列表中指定位置的元素(可选操作)。
E get(int index) 返回列表中指定位置的元素。
boolean equals(Object o) 比较指定的对象与列表是否相等。 比较方式按照元素位置依次比较。比较方式:equals
/*public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator e2 = ((List) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}*/
E remove(int index) 移除列表中指定位置的元素(可选操作)。
int indexOf(Object o) 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1
int lastIndexOf(Object o)
List<E> subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视
ArrayList
//List的实现类,大小可变的列表,基于数组,默认初始大小初始为10;每次扩容为原数组的1.5倍。
// 因为ArrayList是基于数组实现的,内存空间是连续的。插入或者删除元素的时候效率会较低。但查询效率很快。
// 线程不安全的集合。
// 练习:用数组实现一个ArrayList(有序表)。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
System.out.println(list.toString());
}
LinkedList
//基于链表。用节点(NODE)储存元素。内存空间不连续,删除和插入效率高。查询元素效率低,线程不安全的集合。
List<String> link = new LinkedList<>();
Vector
List--JDK1.2
// Vector:向量,java中最早的集合之一(JDK.10)。底层基于数组,默认数组长度10,每次扩容1倍.10--20--40,基于三元运算.
// 线程安全的集合。
public static void main(String[] args) {
Vector<String> v = new Vector<>(10, 5);
v.add("a");
// Enumeration<E> elements() 返回此向量的组件的枚举(迭代器)。
// 迭代器,基于指针移动。遍历每个元素。
/*
* boolean hasMoreElements() 测试此枚举是否包含更多的元素。
E nextElement() 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。
*/
Enumeration<String> e = v.elements();
while (e.hasMoreElements()) {
// 移动指针,挪到下一个元素。
String s = (String) e.nextElement();
System.out.println(s);
//v.remove(s);这种方式移不完集合。
}
System.out.println(v.capacity());// 10
}
Stack
// Stack:栈。(Vector的子类),遵循LILO原则(后进先出)。基于Vector实现。线程安全的集合。
// 向栈中添加元素,入栈/压栈。将元素取出:出栈/弹栈。
// 栈底元素:第一个放进的元素。 栈顶元素:最后一个放进去的元素。
// 练习:用数组实现栈结构--pop、push、peek、empty、search
// 总结:list和数组区别?--大小,元素类型,内存空间。
// ArrayList LinkedList Vector的异同点?根据插入的位置不同而不同。
// 从整体(平均)效率上,LinkedList会较快。从局部效率上,在不扩容的前提下,如果插入的位置比较靠后,则ArrayList会比较快。
public static void main(String[] args) {
Stack<String> s = new Stack<String>();
// public E push(E item)
// public synchronized E pop() ;将栈顶元素取出,并移除。
// public synchronized E peek() ;查看栈顶元素,不将栈顶元素取出。
// public synchronized int search(Object o) ;搜索某元素在栈中的位置,下标从1开始。
}
Set
1. Set--不包含重复值。不保证元素的迭代顺序(存入顺序),不保证该顺序恒久不变。
2. set集合的实现类
1. HashSet:
1. 底层基于HashMap的实例实例实现。
2. 要求key不可重复。由哈希算法确定储存桶位置。
3. 允许key为null
3. 线程不安全的集合
2. LinkedHashSet
1. 底层是Hash表和双向链表。
2. 具有可预知迭代顺序的(元素的插入顺序)
3. LinkedHashSet 迭代所需时间与 set 的大小 成正比,而与容量无关
4. 由于增加了维护链接列表的开支,其性能很可能会比 HashSet
5. 影响其性能的参数:初始容量 和加载因子。
6. 线程不安全的集合
3. treeSet
public static void main(String[] args) {
//Set--不包含重复值。不保证元素的迭代顺序(存入顺序),不保证该顺序恒久不变。
/*
* HashSet--底层是HashMap,默认储存空间(桶)16,当元素超桶容量的0.75的时候,则会扩容一倍,并进行reHash操作--重新计算元素的储存位置。。
* 元素在存入到HashSet表中的时候,会根据对象的Hash码值,经哈希算法,计算出元素的存储桶位置。
* 不同的对象有不同的hash码值,但在经过哈希算法计算之后可能产生相同的储存桶位置。
* 那么这个时候就会产生碰撞,碰撞过程--会用equals比较两个对象是否相同,相同则后储存的对象直接舍弃。若不同则会将原来的储存位置向下一位移动。
* 若下一位,也有元素,则也会产生碰撞,知道找个空桶储存为止。
* 碰撞几率问题:碰撞几率和桶容量和加载因子大小有关。我们在创建Set集合的时候可以通过构造函数可以指定容量大小和加载因子。
* 构造--指定容量和加载因子?100-1--碰撞几率增加--效率下降。100-0.5-扩容频繁,内存消耗增加,rehash操作也很频繁。
* 加载因子(警戒线)0.75--若容量超过75%则需扩容。16*0.75=12,当超过12时即13,则会扩容。
*/
Set<String> set = new HashSet<String>();
}
Iterator
1. 迭代器,用于迭代遍历集合---在迭代过程中不允许增删原集合
Iterable提供了一个iterator方法来产生一个Iterator对象。
增强for循环本质上在迭代遍历。---如果一个对象允许使用增强for循环遍历,则这个对象对应的类必须实现Iterable接口。---JDK1.
public class IteratorDemo {
// public interface Iterable<T>(JDK1.5开始):实现这个接口允许对象成为 "foreach" 语句的目标。(提供了一个,可以获取Iterator对象的方法)
// 增强foreach(JDK1.5的特性之一):本质就是迭代器,进行迭代遍历
// JDK1.5新特性:增强foreach,泛型,自动拆封箱
// 在迭代过程中,不允许增加或删除原集合。
// Enumeration接口的功能与 Iterator 接口的功能是重复的。此外,
// Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。
// 新的实现应该优先考虑使用 Iterator
// 接口而不是 Enumeration 接口
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("a");
set.add("b");
set.add("c");
// 获取集合的迭代器
Iterator<String> it = set.iterator();
while (it.hasNext()) {// 判断是否有下一个元素
// 移动指针,获取下一个元素
String str = it.next();
System.out.println(str);
// 移除当前迭代的元素
// 1.将原集合复制 2 每一个元素标记为False
// 3.遍历集合(判断-移动指针(把指针指向的位置标志为T:标识元素是存在)
// 4.当it.remove()时候,会将该指针指向的位置,标记职位F,副本集合再和原集合比较,标记为true保留,false则移除。)
it.remove();
// set.remove();
}
}
Collections
1. 操作集合的工具类提供了很多操作集合的方法。
public class CollectionsDemo {
// Collections:操作集合的工具类。
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("a");
list.add("d");
list.add("ab");
list.add("e");
list.add("f");
// 替换原集合所有的"a"
Collections.replaceAll(list, "a", "1");
System.out.println(list);
// 将集合反转
Collections.reverse(list);
System.out.println(list);
// 集合升序排列
Collections.sort(list);
System.out.println(list);
// 将数组转化为一个集合
List<String> lis = Arrays.asList("John", "Tome", "Toms", "Jack", "Jerry");
// //升序排列
// Collections.sort(lis);
System.out.println(lis);
// 自定义规则:Comparator:接口,比较器,重写Compare方法,将比较规则写到Compare方法中。一个类想要实现自定义排序,可以实现该接口
// Comparable:接口,若果不指定比较规则,一个类想要被自然排序,必须实现该接口,可以重ComparaeTo方法,定义比较规则。
// 按照首字母升序排列
Collections.sort(lis, new Comparator<String>() {
// 返回一个正数,s1>s2,则s1就会排在s2的后面
// 返回0,不做排序
@Override
public int compare(String o1, String o2) {
return o1.charAt(0) - o2.charAt(0);
}
});
System.out.println(lis);
}
}
Comparator
1. 比较器。重写compare方法,将比较规则写到compare方法中。
2. 如果返回一个正数,则意味着第一个参数要排在第二个参数后边;
3. 如果返回一个负数,则意味着第一个参数要排在第二个参数前边。
4. 如果在排序的时候没有指定比较规则,那么这个时候要求排序的元素所对应的类必须实现Comparable接口,重写接口中compareTo方法
下一篇:
基础系列【十四】–Map映射