第十章:集合
-
容器 : 存储对象的方式(数组,集合)
-
一 数组的特点
-
1.数组一旦创建成功,长度不可变。
-
2.声明数组的类型就决定了数组元素的类型
-
二 数组的弊短
-
1.长度不可变(不能自动进行扩容)
-
2.数组的API和属性比较少。没有添加,删除,插入等操作。(缺少元素个数的属性/方法。)
-
3.数组只能用来存放有序的可重复的数据。对于无序的不可重复的无能为力。
-
三 Collection
-
List : 有序的且可重复
-
Set : 无序的且不可重复
-
增强for循环
-
作用 : 只能用来遍历集合和数组的元素
-
格式 :
-
for(元素的类型 临时变量 : 集合、数组的对象){
-
}
-
interator() : 调用这个方法会返回一个Iterator接口的实现类的对像
-
Iterator接口 : 遍历集合中的元素
-
Collection :
-
|---List : 有序的且可重复的
-
|---Set : 无序的且不可重复
在当前集合的index位置添加ele元素
void add(int index, Object ele)
在当前集合的index位置插入eles中所有的元素
boolean addAll(int index, Collection eles)
获取当前集合index位置上的元素
Object get(int index)
obj在当前集合的索引 - 从前向后找
int indexOf(Object obj)
obj在当前集合的索引 - 从后向前
int lastIndexOf(Object obj)
将当前集合index位置上的元素删除掉,并返回
Object remove(int index)
将当前集合index位置上的元素改成ele
Object set(int index, Object ele)
截取当前集合fromIndex到toIndex的元素组成新的集合.左闭右开
List subList(int fromIndex, int toIndex)
-
|—List:
-
|--- ArrayList : 是List的主要实现类
-
|--- Vector : 不用了
-
|--- LinkedList : 底层是链表
-
[面试题] List的主要实现类有哪些?有什么不同?
ArrayList : List的主要实现类,底层是数组,线程不安全,查找快,增删慢(数组的特点)。
Vector : 古老的实现类,底层是数组,线程安全的
LinkedList : 底层是使用双向链表。增删快,查找慢。 -
[面试题]ArrayList的底层实现原理?
通过ArrayList空参的构造器创建对象。底层会创建一个长度为10的数组。
当我们向数组中添加第11个元素时 -
底层会进行扩容,扩容为原来的1.5倍(创建一个新的数组长度为原来的1.5倍并将原数组中的内容添加到新的数组中)。
-
Collection子接口之Set
-
Set : 无序的不可重复的
-
|----Set :
-
|---- HashSet: 是Set的主要实现类
-
|--- LinkedHashSet :继承了HashSet。底层实现原理和HashSet一样。可以安照元素添加的顺序进行遍历。它维护了一张链表该链表记录了元素添加的顺序。
-
|---- TreeSet :
-
无序性:不是指的随机性,通过hashCode方法算出来的值来决定,数据在数组中存放的位置
-
不可重复:进行euqals方法的比较。如果结果是true则认为两个数据相同,如果是false则认为两个数据不相同
-
[面试题]HashSet的底层实现原理?
-
当我们向HashSet中添加一个数据时。会先调用该数据的hashCode方法来决定该数据在数组中所存放的位置。
-
如果该位置上没有其它元素,则将该数据直接存放即可。如果该位置上已经有了其它的元素,调用该元素所在类的equals方法
-
进行比较。如果返回值是个true则认为两个数据相同则不能存放。如果返回值是个false则以链表的形式将该数据存在该位置上。
-
(jdk1.8)如果数量达到8则将链表换成红黑树。
-
TreeSet
-
1.底层就是一个红黑树
-
2.可以对元素进行排序
-
3.TreeSet中的元素的类型必须保持一致
-
两种排序方式
-
一 自然排序
-
1.自定义类需要实现Comparable接口
-
2.需要重写compareTo方法
-
3.安照某个属性进行排序
-
4.向集合中添加元素
-
二 定制排序
-
1.创建一个Compartor实现类的对象,并传入到TreeSet的构造器中
-
2.重写compare方法
-
3.安照某个属性进行排序
-
4.向集合中添加元素
-
思考:
-
1.如果即有自然排序又有定制排序那么谁起作用? 定制排序
-
2.自然排序和定制排序哪个更好一些?定制排序更灵活一些
-
LinkedHashSet: 继承了HashSet。底层实现原理和HashSet一样。
-
可以安照元素添加的顺序进行遍历。它维护了一张链表该链表记录了元素添加的顺序。
-
自然排序
-
1.自定义类需要实现Comparable接口
-
2.需要重写compareTo方法
-
3.安照某个属性进行排序
-
4.向集合中添加元素
public class SetTest {
@Test
public void test4(){
//向构造器中传入一个Compartor实现类的对象
TreeSet set = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Animal && o2 instanceof Animal){
Animal a = (Animal) o1;
Animal a2 = (Animal) o2;
//排序
return a.age - a2.age;
}
return 0;
}
});
set.add(new Animal("aaa",18));
set.add(new Animal("bbb",8));
set.add(new Animal("fff",38));
set.add(new Animal("ccc",28));
System.out.println(set);
}
@Test
public void test3(){
TreeSet set = new TreeSet();
// set.add(12);
// set.add(5);
// set.add(123);
// set.add(6);
// set.add(9);
// set.add("aaa");
// set.add("fff");
// set.add("ddd");
// set.add("ccc");
set.add(new Student("aaa",18));
set.add(new Student("ccc",28));
set.add(new Student("ddd",28));
set.add(new Student("fff",28));
set.add(new Student("kkk",28));
set.add(new Student("lll",28));
set.add(new Student("eee",38));
System.out.println(set);
}
/*
* LinkedHashSet: 继承了HashSet。底层实现原理和HashSet一样。
* 可以安照元素添加的顺序进行遍历。它维护了一张链表该链表记录了元素添加的顺序。
*
*/
@Test
public void test2(){
Set set = new LinkedHashSet();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("ddd");
set.add("aaa");
System.out.println(set);
}
@Test
public void test(){
Set set = new HashSet();
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("ddd");
set.add("aaa");
set.add(new Person("aaa",18));
set.add(new Person("aaa",18));
System.out.println(set);
}
}
public class Animal {
String name;
int age;
public Animal() {
super();
}
public Animal(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "(" + name + " " + age + ")";
}
}
public class Person {
String name;
int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
System.out.println("------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) {
System.out.println("---------equals----------");
// 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 false;
}
@Override
public String toString() {
return "(" + name + " " + age + ")";
}
}
public class Student implements Comparable {
String name;
int age;
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "(" + name + " " + age + ")";
}
@Override
public int compareTo(Object o) {
if(o instanceof Student){
Student s = (Student) o;
//安年纪排序
// return -(this.age - s.age);
//安名字排序
// return this.name.compareTo(s.name);
//安年纪排序如果相同安名字排序
int a = this.age - s.age;
//如果年纪相同
if(a == 0){
//比较名字
return this.name.compareTo(s.name);
}
return a;
}
//0代表两个数据是相同的
return 0;
}
}
public class ListTest {
/*
* void addFirst(Object obj)
void addLast(Object obj)
Object getFirst()
Object getLast()
Object removeFirst()
Object removeLast()
*/
@Test
public void test2(){
LinkedList list = new LinkedList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.addFirst(111);
list.addLast(222);
System.out.println(list);
System.out.println(list.getFirst());
System.out.println(list.getLast());
list.removeFirst();
list.removeLast();
System.out.println(list);
}
@Test
public void test(){
//底层创建一个长度为10的数组
ArrayList list = new ArrayList();
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
System.out.println(list);
}
}
public class ListAPI {
/*
* 面试题
*/
@Test
public void test3(){
List list2 = new ArrayList();
list2.add(1); //自动装箱
list2.add("aaa");
/*
* 思考 : 删除的是1这个内容,还是索引值中的元素
*/
// list2.remove(1); //1是索引值
list2.remove(new Integer(1)); //删除的是内容
list2.rem
System.out.println(list2);
}
@Test
public void test2(){
List list2 = new ArrayList();
list2.add("aaa");
list2.add("bbb");
list2.add("ccc");
list2.add("aaa");
// Object remove = list2.remove(2);
// System.out.println(remove);
// list2.set(0, "AAA");
List subList = list2.subList(0, 2);
System.out.println(subList);
System.out.println(list2);
}
@Test
public void test(){
List list = new ArrayList();
list.add(111);
list.add(222);
list.add(333);
// list.add(0, "aaa");
List list2 = new ArrayList();
list2.add("aaa");
list2.add("bbb");
list2.add("ccc");
list2.add("aaa");
// list.addAll(0, list2);
System.out.println(list.get(0));
System.out.println(list);
System.out.println("-----------------");
System.out.println(list2.indexOf("aaa"));
System.out.println(list2.lastIndexOf("aaa"));
}
}
public class IteratorTest {
@Test
public void error(){
}
int sum = 0;
int[] numbers = null;
public void addObject(int obj){
numbers = new int[10];
numbers[sum++] = obj;
}
/*
* 常见错误
*/
@Test
public void test2(){
Collection c = new ArrayList();
c.add(123);
c.add("aaa");
c.add(222);
c.add(333);
/*
Iterator iterator = c.iterator();
while(iterator.next() != null){
System.out.println(iterator.next());
}
*/
/*
* c.iterator() : 因为每次都会创建一个新的对象。所以不行
while(c.iterator().hasNext()){
System.out.println(c.iterator().next());
}
*/
}
@Test
public void test(){
Collection c = new ArrayList();
c.add(123);
c.add("aaa");
c.add(222);
c.add(333);
//返回一个Iterator接口实现类的对象
Iterator iterator = c.iterator();
//next() : 作用 : 1.指针下移 2.返回指针指向的元素
// Object obj = iterator.next();
// System.out.println(obj);
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// for(int i = 0;i < 4; i++){
// System.out.println(iterator.next());
// }
//hasNext() : 如果还有下一个元素则返回true
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
public class ForEachTest {
/*
* 演示(理解)
*/
@Test
public void test3(){
String[] names = {"gg","jj","dd","mm"};
/*
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]);
//给数组的元素赋值
names[i] = "aa";
}
for (String string : names) {
System.out.println(string);
}
*/
/*
* 下面的例子可以理解成下面的形式
* String name = names[i];
* name = "aa";
*/
for (String name : names) {
System.out.println(name);
//没有改变数组中的元素,因为改变的是临时变量的值
name = "aa";
}
for (String string : names) {
System.out.println(string);
}
}
/*
* 遍历数组的元素
*/
@Test
public void test2(){
String[] names = {"aa","bb","cc","dd"};
for(String name : names){
System.out.println(name);
}
}
/*
* 遍历集合中的元素
*/
@Test
public void test(){
Collection c = new ArrayList();
c.add(123);
c.add("aaa");
c.add(222);
c.add(333);
for(Object obj : c){
System.out.println(obj);
}
}
}
public class CollectionTest {
/*
* API第四波
*/
@Test
public void test4(){
Collection c = new ArrayList();
c.add(111);
c.add(222);
c.add("aaa");
c.add("bbb");
Collection c2 = new ArrayList();
c2.add(111);
c2.add(222);
c2.add("ccc");
/*
* retainAll(Collection coll)只保留当前集合和coll中交集(相同的元素)的元素。
*/
//c.retainAll(c2);
//System.out.println(c);
Collection c3 = new ArrayList();
c3.add("aaa");
c3.add("ddd");
c3.add("ccc");
//将一个集合转化成一个数组
Object[] array = c3.toArray();
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
}
/*
* API第三波
*/
@Test
public void test3(){
Collection c = new ArrayList();
c.add(111);
c.add(222);
c.add("aaa");
c.add("bbb");
//remove(Object obj)从当前集合中删除obj这个元素。删除失败返回false
//c.remove(111);
Collection c2 = new ArrayList();
c2.add(111);
c2.add(222);
c2.add("ccc");
//removeAll(Collection coll) 将当前集合和coll集合中交集(相同的元素)的元素从当前集合中删除掉。
c.removeAll(c2);
System.out.println(c);
}
/*
* API第二波
*
* 注意 : 凡是向Collection中添加的自定义类的对象,自定义类的对象都需要重写equals方法
*/
@Test
public void test2(){
Collection c = new ArrayList();
c.add(111);
c.add(222);
c.add("aaa");
c.add("bbb");
//c.add(new Person("abc",19));
//contains(Object obj) : 当前集合是否包含obj这个元素
boolean contains = c.contains("aaa");
System.out.println(contains);
/*
* 如果集合中的元素是自定义类的对象。那么查找对象的时候比较的是地址值。
* 如何比较属性呢?
* 重写equals()
*/
System.out.println(c.contains(new Person("abc",19)));
System.out.println("--------------------------------------------");
Collection c2 = new ArrayList();
c2.add(111);
c2.add(222);
//containsAll(Collection coll) : 当前集合是否包含coll集合中所有的元素
boolean containsAll = c.containsAll(c2);
System.out.println(containsAll);
System.out.println("--------------------------------");
Collection c3 = new ArrayList();
c3.add(111);
c3.add(222);
c3.add(222);
//equals(Object obj) 比较两个集合中的元素是否相等。(类型,个数,内容)
System.out.println(c2.equals(c3));
System.out.println("-----------------------------");
System.out.println(c3.hashCode());
System.out.println(c2.hashCode());
}
/*
* API第一波
*/
@Test
public void test(){
//多态 : 接口和类之间的多态性,接口的类型 = 接口的实现类的对象,接口可以看成父类,接口的实现类可以看成子类
Collection c = new ArrayList();
//add(Object obj) : 向集合中添加一个元素
c.add(123); //自动装箱
c.add("aaaa");
c.add("aaaa");
c.add(new Person("范冰冰",18)); //重写了Person类的toString方法,输出内容,如果没有重写Person类的toString则输出地址值
Collection c2 = new ArrayList();
c2.add(111);
c2.add(222);
//addAll(Collection coll) : 将coll集合中的每一个元素分别添加到当前的集合中
c.addAll(c2);
//isEmpty() : 如果该集合没有元素则返回true
System.out.println(c.isEmpty());
System.out.println("--------clear后---------------");
//clear() : 移除集合中的所有的元素
c.clear();
System.out.println(c.isEmpty());
System.out.println(c);
//size()集合中元素的个数
System.out.println(c.size());
}
}
package com.atguigu.java;
public class Person {
String name;
int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
// System.out.println("-----equals-------------");
if(this == obj){
return true;
}
if(obj instanceof Person){
Person p = (Person) obj;
return p.name.equals(this.name) && p.age == this.age;
}
return false;
}
@Override
public String toString() {
return "(" + name + " " + age + ")";
}
}
下一篇: 集合的知识点