1. Collection的使用
1.1 常用方法
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
// @Override
// public int hashCode() {
// int result = name != null ? name.hashCode() : 0;
// result = 31 * result + age;
// return result;
// }
}
/**
* 测试Collection中的常用方法
* 三个层面(递进关系)
* * 层次一:掌握不同接口的主要实现类的实例化,及常用方法 (ArrayList\HashSet\HashMap)
* * 层次二:掌握不同实现类之间的区别
* * 层次三:常用的集合类的底层实现原理--->数据结构。 (ArrayList\LinkedList\HashMap)
*
*/
public class CollectionTest {
@Test
public void test1(){
//1. add(Object obj):将obj元素添加到Collection中
Collection coll1 = new ArrayList();
coll1.add(123);//自动装箱
coll1.add("AA");
coll1.add(new Date());
//2. size():获取集合中元素的个数
System.out.println(coll1.size());
//3. addAll(Collection coll2):将coll2中的元素都添加到当前集合中
Collection coll2 = new ArrayList();
coll2.add(456);
coll2.add("BB");
coll2.add("AA");
coll1.addAll(coll2);
System.out.println(coll1.size());//6
System.out.println(coll1);
//5. clear():清空集合中的元素
coll1.clear(); //与coll1 = null;不同
//4. isEmpty():是否为空
System.out.println(coll1.isEmpty());
System.out.println(coll1.size());
}
@Test
public void test2(){
Collection coll1 = new ArrayList();
coll1.add(123);//自动装箱
coll1.add(new String("AA"));
coll1.add(new Date());
coll1.add(123);//自动装箱
coll1.add(new Person("Tom",12));
//6. contains(Object obj):判断当前集合中是否包含元素obj
System.out.println(coll1.contains(123));//true
System.out.println(coll1.contains(new String("AA")));//true
System.out.println(coll1.contains(new Person("Tom",12)));//false --> true
//7. constainsAll(Collection coll2):判断当前集合中是否包含coll2中的所有元素
Collection coll2 = new ArrayList();
// coll2.add(456);
// coll2.add("BB");
coll2.add("AA");
coll2.add(new Integer(123));
System.out.println(coll1.containsAll(coll2));
//8.remove(Object obj):删除集合中的obj元素
// System.out.println(coll1);
// coll1.remove(123);
// System.out.println(coll1);
//9. removeAll(Collection coll2):差集,从当前集合中删除掉其与coll2共有的元素
System.out.println(coll1);
coll1.removeAll(coll2);
System.out.println(coll1);
}
@Test
public void test3(){
Collection coll1 = new ArrayList();
coll1.add(123);//自动装箱
coll1.add(new String("AA"));
coll1.add(123);//自动装箱
coll1.add(new Person("Tom",12));
//10.retainAll(Collection coll2):
// Collection coll2 = new ArrayList();
// coll2.add("AA");
// coll2.add(new Integer(123));
//
// coll1.retainAll(coll2);//交集:获取当前集合与coll2共有的元素
// System.out.println(coll1);
//11.equals(Object obj):判断两个元素是否相等
Collection coll3 = new ArrayList();
coll3.add(new String("AA"));
coll3.add(123);//自动装箱
coll3.add(123);//自动装箱
coll3.add(new Person("Tom",12));
System.out.println(coll1.equals(coll3));
//12. hashCode():返回当前对象的哈希值
System.out.println(coll1.hashCode());
//13. Object[] toArray():将集合转换为数组
Object[] arr = coll1.toArray();
System.out.println(Arrays.toString(arr));
//数组-->集合:调用Arrays工具类的asList(Object ... objs)
Object[] arr1 = new Object[]{123,"AA",new Date()};
List<Object> list = Arrays.asList(arr1);
System.out.println(list);
List list1 = Arrays.asList(123, "AA", new Date());
System.out.println(list1);
}
}
结论:向Collection集合中添加的元素,要求元素所属的类必须重写equals()
- 需要掌握Collection 与 数组之间的相互转换
1.2 Iterator的使用
- 作用:Iterator就是用来遍历Collection集合的。
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 测试Collection集合的遍历操作
*
*
* Iterator接口就是用来遍历Collection集合元素的。
*
*/
public class IteratorTest {
@Test
public void test1(){
Collection coll1 = new ArrayList();
coll1.add(new String("AA"));
coll1.add(123);//自动装箱
coll1.add(456);//自动装箱
coll1.add(new Person("Tom",12));
// System.out.println(coll3);
//得到Iterator迭代器接口的对象
Iterator iterator = coll1.iterator();
// System.out.println(iterator.getClass());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());
// System.out.println(iterator.next());//如果调用的次数超过了集合中元素的个数,报NoSuchElementException
//写法1:强烈不建议
// for(int i = 0;i < coll1.size();i++){
// System.out.println(iterator.next());
// }
//写法2:推荐
while(iterator.hasNext()){
//next():① 指针下移 ② 将下移以后指针指向的集合位置上的元素返回
System.out.println(iterator.next());
}
//错误写法1:
// while(iterator.next() != null){
// System.out.println(iterator.next());
// }
//错误写法2:
// while(coll1.iterator().hasNext()){
// System.out.println(coll1.iterator().next());
// }
}
}
1.3 增强for循环
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
/**
* 增强for循环的使用
*
*/
public class ForTest {
@Test
public void test1(){
Collection coll1 = new ArrayList();
coll1.add(new String("AA"));
coll1.add(123);//自动装箱
coll1.add(456);//自动装箱
coll1.add(new Person("Tom",12));
/*
for(元素的类型 变量名 :集合对象)
*/
for(Object obj : coll1){
System.out.println(obj);
}
}
@Test
public void test2(){
int[] arr = new int[]{1,2,2,3,4};
for(int i : arr){
System.out.println(i);
}
}
//对比方式一和方式二
@Test
public void test3(){
int[] arr = new int[]{1,2,2,3,4};
//方式一:
// for(int i = 0;i < arr.length;i++){
// arr[i] = 5;
// }
//方式二:
for(int i : arr){
i = 5;
}
for(int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
}
}
}
2. List接口的使用(重点)
2.1 主要实现类的使用:ArrayList
/*
void add(int index, Object ele):在index位置插入ele元素
boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
Object get(int index):获取指定index位置的元素
int indexOf(Object obj):返回obj在集合中首次出现的位置
int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index, Object ele):设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
总结:
增:add(Object obj)
删:remove(Object obj) / remove(int index)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
长度:size()
遍历:使用Iterator、增强for、一般的for
*/
@Test
public void test1(){
List list = new ArrayList();
list.add(1);//自动装箱
list.add("AA");
list.remove(new Integer(1));
System.out.println(list);
}
2.2 实现类的对比
java.util.Collection:存储一个一个的数据
* * |----java.util.List:存储有序的、可重复的数据。 ----> “动态”数组
* * |---- ArrayList : List的主要实现类;线程不安全的,效率高;底层使用Object[]存储
* |---- LinkedList :对于频繁的插入、删除操作,效率高,建议使用此类;底层使用双向链表存储
* |---- Vector : List的古老实现类;线程安全的,效率低;底层使用Object[]存储
* 面试题:区分ArrayList、LinkedList、Vector * * 数据结构:① 数据的逻辑关系? ② 数据的存储结构: 顺序表(数组)、链表 ; ADT(abtract data tye):栈、队列、树、图 * * 顺序表:尾部添加、查询、修改的效率高O(1),插入、删除操作的效率低O(n) * 链表:插入、删除操作的效率高O(1),尾部添加、查询、修改的效率低O(n)
2.3 源码分析
- ArrayList
ArrayList 的底层源码:
* 在jdk7中:
* ArrayList list = new ArrayList();// 底层创建了长度为10的Object[] elementData
*
* list.add(128);//elementData[0] = new Integer(128);
* ...
* 当要存储第11个元素时,需要扩容,默认为原来的1.5倍,并将原有的元素复制到新的数组中。
* ...
* 在jdk8中:
* ArrayList list = new ArrayList();//底层的Object[] elementData初始化为{}
* list.add(128); //首次添加一个元素,elementData重新初始化为长度为10的数组,并elementData[0] = new Integer(128);
* ...
* 当要存储第11个元素时,需要扩容,默认为原来的1.5倍,并将原有的元素复制到新的数组中。
* ...
*
* ....
- Vector
Vector的底层源码:
* 在jdk7和jdk8中是相同的操作:
* Vector vec = new Vector();//底层创建了长度为10的Object[] elementData
* vec.add(128);//elementData[0] = new Integer(128);
* ....
* 当要存储第11个元素时,需要扩容,默认为原来的2倍,并将原有的元素复制到新的数组中。
- LinkedList
LinkedList的底层源码:
*
* LinkedList list = new LinkedList();
* list.add(128);//
* ...
* 不断的添加即可,不涉及扩容的问题。
*
* 证明底层是双向链表:
* private static class Node<E> {
* E item;
* Node<E> next;
* Node<E> prev;
*
* Node(Node<E> prev, E element, Node<E> next) {
* this.item = element;
* this.next = next;
* this.prev = prev;
* }
* }
*
启示: 1. 如果开发中要使用ArrayList,在大体清楚元素个数情况下,建议使用 ArrayList(int capacity) 2. 对于频繁的插入、删除操作,建议使用LinkedList
3. Set接口的使用
3.1 主要实现类的使用:HashSet
/*
Set在 Collection的基础上,没有新增的方法。
*/
/*
Set的主要实现类是HashSet。通过HashSet体会Set的特点
1. 不可重复性:按照equals()进行判断,不能有返回值为true的元素。
2. 无序性:不等于随机性。有别于数组存储数据时,依次紧密排列。
元素到底存储在数组中的哪个位置呢?由添加的元素所在的类重写的hashCode()决定的。
*/
@Test
public void test1(){
HashSet set = new HashSet();
set.add(123);//自动装箱
set.add("AA");
set.add(new String("BB"));
set.add(new String("BB"));
set.add(new Person("Tom",12));
set.add(new Person("Tom",12));
// System.out.println(set);
//使用迭代器
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//使用增强for循环
for(Object obj : set){
System.out.println(obj);
}
//使用一般for循环:不行
}
3.2 实现类的对比
/* 一、
* java.util.Collection:存储一个一个的数据
* |----java.util.Set:存储无序的、不可重复的数据 ----> 高中学的"集合"
* |---- HashSet:作为Set的主要实现类
* |---- LinkedHashSet:作为HashSet的子类,遍历集合元素时,可以实现按照添加元素的顺序实现遍历。
* 对于频繁的遍历操作,建议使用此类。
* 原因:在HashSet的基础上,给每个元素提供了一对指针,记录这个元素之前的和之后的元素。
* |---- TreeSet:可以按照添加的元素的指定的属性的大小顺序实现遍历。 (了解)
* 向TreeSet中添加的元素的要求:
* ① 必须是同一个类型的元素
* ② 元素需要考虑排序的方式:a.自然排序 b.定制排序
* 二、结论:
* 1. 向Set集合中添加的元素,要求其所在的类必须重写两个方法:equals()、hashCode() --->主要针对的是HashSet
* 2. 对于TreeSet来说,判断数据是否重复,不参考equals()、hashCode(),只是参考自然排序中的compareTo() 或定制排序中的compare().
*/
- LinkedHashSet
@Test
public void test2() {
HashSet set = new LinkedHashSet();
set.add(123);//自动装箱
set.add("AA");
set.add(new String("BB"));
set.add(new String("BB"));
set.add(new Person("Tom", 12));
System.out.println(set);
}
- TreeSet
import com.sun.corba.se.impl.orb.ParserTable;
import org.junit.Test;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetTest {
@Test
public void test1(){
TreeSet set = new TreeSet();
set.add("CC");
// set.add(123);
set.add("AA");
set.add("DD");
set.add("MM");
set.add("GG");
set.add("JJ");
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test2(){
TreeSet set = new TreeSet();
Person p1 = new Person("Tom",12);
Person p2 = new Person("Jack",34);
Person p3 = new Person("Rose",2);
Person p4 = new Person("Jerry",43);
Person p5 = new Person("Tommy",22);
Person p6 = new Person("Tony",12);
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
set.add(p5);
set.add(p6);
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
//定制排序
@Test
public void test3(){
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Person && o2 instanceof Person){
Person p1 = (Person)o1;
Person p2 = (Person)o2;
return p1.getName().compareTo(p2.getName());
}
throw new RuntimeException("输入的类型不匹配");
}
};
TreeSet set = new TreeSet(comparator); //类比:Arrays.sort(arr,comparator)
Person p1 = new Person("Tom",12);
Person p2 = new Person("Jack",34);
Person p3 = new Person("Rose",2);
Person p4 = new Person("Jerry",43);
Person p5 = new Person("Tommy",22);
Person p6 = new Person("Tony",12);
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
set.add(p5);
set.add(p6);
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
import java.util.Comparator;
public class Person implements Comparable {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public boolean equals(Object o) {
System.out.println("Person equals()....");
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
//指名排序方式:年龄从小到大
@Override
public int compareTo(Object o) {
// if(o instanceof Person){
// Person p = (Person)o;
// return this.age - p.age;
// }
// throw new RuntimeException("输入的类型不匹配");
if(o instanceof Person){
Person p = (Person)o;
int ageValue= this.age - p.age;
if(ageValue != 0){
return ageValue;
}
return this.name.compareTo(p.name);
}
throw new RuntimeException("输入的类型不匹配");
}
}
3.3 源码分析 --略
HashSet的底层源码就是HashMap。我们直接关注HashMap即可。
4. Map接口的使用(重点)
4.1 Map存储数据的特点
Map的理解:(主要针对的是HashMap)
* Map中的所有的key彼此是不可重复的、是无序的。所有的key构成的集合是一个Set --->要求key所在的类要重写equals()和hashCode()
* Map中的所有的value彼此是可重复的、是无序的。所有的value构成的集合是一个Collection --->要求value所在的类要重写equals()
* Map中的一个key-value构成一个entry,作为entry的两个属性出现的。
* Map中的所有的Entry彼此是不可重复的、是无序的。所有的entry构成的集合是一个Set
4.2 主要实现类HashMap及常用方法
public class MapTest {
@Test
public void test1(){
HashMap map = new HashMap();
//1. 添加\修改:Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
map.put("Tom",67);
map.put(56,"AA");
map.put(null,"AA");
map.put(67,null);
map.put("Tim",78);
map.put("Tim",98);
//2. int size():返回map中key-value对的个数
System.out.println(map.size());
System.out.println(map);
//3. Object remove(Object key):移除指定key的key-value对,并返回value
map.remove(67);
System.out.println(map);
//4. void clear():清空当前map中的所有数据
map.clear();
//5. boolean isEmpty():判断当前map是否为空
System.out.println(map.isEmpty());
}
@Test
public void test2(){
HashMap map = new HashMap();
map.put("Tom",67);
map.put(56,"AA");
map.put(null,"AA");
map.put(67,null);
map.put("Tim",78);
//6. Object get(Object key):获取指定key对应的value
Object value = map.get(566);
System.out.println(value);
//boolean containsKey(Object key):是否包含指定的key
System.out.println(map.containsKey("Tom"));
// boolean containsValue(Object value):是否包含指定的value
System.out.println(map.containsValue("AA"));
}
@Test
public void test3(){
HashMap map = new HashMap();
map.put("Tom",67);
map.put(56,"AA");
map.put(null,"AA");
map.put(67,null);
map.put("Tim",78);
//Set keySet():返回所有key构成的Set集合
Set set = map.keySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println();
//Collection values():返回所有value构成的Collection集合
Collection values = map.values();
Iterator iterator1 = values.iterator();
while(iterator1.hasNext()){
System.out.println(iterator1.next());
}
System.out.println();
//Set entrySet():返回所有key-value对构成的Set集合
Set entrySet = map.entrySet();
Iterator iterator2 = entrySet.iterator();
while(iterator2.hasNext()){
Map.Entry entry = (Map.Entry) iterator2.next();
System.out.println(entry.getKey() + "--->" + entry.getValue());
}
System.out.println("*****");
Set set1 = map.keySet();
Iterator iterator3 = set.iterator();
while(iterator3.hasNext()){
Object key = iterator3.next();
System.out.println(key + "******" + map.get(key));
}
}
}