集合的结构:
1.Collection集合的基本功能:
boolean add(E e)
boolean remove(Object o)
void clear()
boolean contains(Object o)
boolean isEmpty()
int size()
2.Collection集合的带All功能:
boolean addAll(Collection c):
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("c");
c2.add("d");
//c1.addAll(c2); //将c2中的每一个元素添加到c1中
c1.add(c2); //将c2看成一个对象添加到c1中
System.out.println(c1);
boolean removeAll(Collection c):
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("z");
boolean b = c1.removeAll(c2); //删除的是交集
System.out.println(b);
System.out.println(c1);
boolean containsAll(Collection c)
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("z");
boolean b = c1.containsAll(c2); //判断调用的集合是否包含传入的集合
System.out.println(b);
boolean retainAll(Collection c):
Collection c1 = new ArrayList();
c1.add("a");
c1.add("b");
c1.add("c");
c1.add("d");
Collection c2 = new ArrayList();
c2.add("a");
c2.add("b");
c2.add("c");
c2.add("d");
c2.add("e");
c2.add("f");
//取交集,如果调用的集合改变就返回true,如果调用的集合不变就返回false
boolean b = c1.retainAll(c2); //取交集
System.out.println(b);
System.out.println(c1);
3.迭代器
概述:
集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
使用:
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());
}
4.List集合的特有功能概述:
void add(int index,E element)
E remove(int index)
E get(int index)
E set(int index,E element)
5.集合框架(List的三个子类的特点)
List的三个子类的特点
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
Vector相对ArrayList查询慢(线程安全的)
Vector相对LinkedList增删慢(数组结构)
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
Vector和ArrayList的区别
Vector是线程安全的,效率低
ArrayList是线程不安全的,效率高
共同点:都是数组实现的
ArrayList和LinkedList的区别
ArrayList底层是数组结果,查询和修改快
LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
共同点:都是线程不安全的
7.LinkedList的特有功能:
public void addFirst(E e)及addLast(E e) //从部开始添加及从尾部开始增加
public E getFirst()及getLast() //获取集合的第一个及最后一个
public E removeFirst()及public E removeLast() //删除集合的第一个及最后一个
public E get(int index);
8.集合迭代集合框架(三种迭代的能否删除):
* 普通for循环,可以删除,但是索引要--,因为数组删除一个元素后,其余的元素向前补充。
for(int i = 0; i < list.size(); i++) {
if("b".equals(list.get(i))) {
list.remove(i--); //通过索引删除元素
}
}
* 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
Iterator<String> it = list.iterator();
while(it.hasNext()) {
if("b".equals(it.next())) {
//list.remove("b"); //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
it.remove();
}
}
* 增强for循环不能删除
for (String string : list) {
if("b".equals(string)) {
list.remove("b");
}
}
9.集合框架(可变参数的概述和使用)
- A:可变参数概述
- 定义方法的时候不知道该定义多少个参数
- B:格式
- 修饰符 返回值类型 方法名(数据类型… 变量名){}
- C:注意事项:
- 这里的变量其实是一个数组
- 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
public static void main(String[] args) {
int[] arr = {11,22,33,44,55};
//print(arr);
print(11,22,33,44,55);
System.out.println("---------------");
//print();
}
/*public static void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}*/
public static void print(int ... arr) { //可变参数其实是一个数组
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
- HashSet
特点:a.保证存储元素的唯一性
b.输出元素无序性
hashSet保持元素的唯一性原理:
当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后 在集合中查找是否有哈希值相同的对象
* 如果没有哈希值相同的对象就直接存入集合
* 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false
就存入, true则不存
所以在存储自定义对象时,需在实体类中重新hashCode和equals方法:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
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;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
- LinkedHashSet
特点:底层是link结构
保证怎么存的就怎么取
public static void main(String[] args) {
LinkedHashSet<String> ls = new LinkedHashSet<>();
ls.add("b");
ls.add("a");
ls.add("s");
ls.add("c");
for (String string : ls) {
System.out.println(string);
}
}
- TreeSet
特点:底层是二叉树
用于排序
使用实例(string和Integer会排序):
a.存在对象实例并按照指定顺序排序:
public static void main(String[] args) {
TreeSet<Person> ts = new TreeSet<>();
ts.add(new Person("张三",24));
ts.add(new Person("李四",22));
ts.add(new Person("王五",23));
ts.add(new Person("赵六",25));
for (Person person : ts) {
System.out.println(person);
}
}
b.在实体类中实现Comparable并重写compareTo方法
返回-1:排在前面,返回0:不存储,返回正数:排在后面
//按照年龄大小来排序
public int compareTo(Person o) {
return this.age - o .age;
}
c.自定义比较器:
按字符串的长度作为比较的顺序:
class compareByLen implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
}
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<>(new compareByLen() );
ts.add("a");
ts.add("cccc");
ts.add("ass");
ts.add("addd");
ts.add("assssssssssssss");
for (String string : ts) {
System.out.println(string);
}
}
d.使用方式
* 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