1:集合
(1)集合的由来和特点
A:由来
java中描述数据的最基本单位就是类,为了方便对多个对象进行存储和遍历,
java提供了一种新的存储数据的容器,叫集合类。
B:特点
长度可以变化。
只能存储对象。
(2)集合和数组的区别
A:集合
只能存储对象
长度可以变化
B:数组
可以存储基本数据类型,也可以存储对象类型
长度固定
(3)集合体系的由来
由于每个集合类的数据结构不同,所以,集合会有很多的子类。
但是,这些子类不断的向上抽取共性内容,最终形成了集合体系。
一个体系的学习和使用方式:
学习顶层:顶层定义的是这个体系的共性内容。
使用底层:底层才是具体的存在的实现类。
(4)学习集合的体系
Collection
|--List
|--ArrayList
|--Vector
|--LinkedList
|--Set
|--HashSet
|--TreeSet
Collection中的功能:
添加元素:
boolean add(Object obj)
删除元素:
void clear()
boolean remove(Object obj)
判断元素:
boolean isEmpty()
boolean contains(Object obj)
长度:
int size()
迭代器:
Iterator iterator()
(5)Collection的功能演示
存储元素
遍历元素
步骤:
创建集合对象
创建元素对象
把元素对象添加到集合对象中
通过迭代器遍历集合元素
A:存储字符串
//创建集合对象
Collection c = new ArrayList();
//创建元素对象
String s1 = "haha";
String s2 = "hehe";
String s3 = "xixi";
//把元素对象添加到集合对象中
c.add(s1);
c.add(s2);
c.add(s3);
通过迭代器遍历集合元素
Iterator it = c.iterator();
while(it.hasNext())
{
String s = (String) it.next();
System.out.println(s);
}
2:List
(1)掌握如下体系结构图
List 元素有序,可重复。
|--ArrayList
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
|--Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
|--LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
(2)List的特有功能
A:添加元素
add(int index,Object obj)
B:删除元素
remove(int index)
C:获取元素
get(int index)
D:列表迭代器
ListIterator listIterator()
E:修改元素
set(int index,Object obj)
案例:
**存储遍历字符串
//创建集合对象
List list = new ArrayList();
//创建元素对象
String s1 = "haha";
String s2 = "hehe";
String s3 = "xixi";
//把元素对象添加到集合对象中
list.add(s1);
list.add(s2);
list.add(s3);
通过迭代器遍历集合元素
Iterator it = list.iterator();
while(it.hasNext())
{
String s = (String) it.next();
System.out.println(s);
}
**存储遍历自定义对象(Student已经存在,name和age)
List list = new ArrayList();
Student s1 = new Student("东方不败",20);
Student s2 = new Student("岳不群",25);
Student s3 = new Student("林平之",22);
list.add(s1);
list.add(s2);
list.add(s3);
//遍历
Iterator it = list.iterator();
while(it.hasNext())
{
Student s = (Student)it.next();
System.out.println(s.getName()+"***"+s.getAge());
}
for(int x=0; x<list.size(); x++)
{
Student s = (Student) list.get(x);
System.out.println(s.getName()+"***"+s.getAge());
}
(3)List体系下的这个三个集合类用哪一个比较好:
A:如果是要求查询快,就使用ArrayList
B:如果是要求增删多比较多,就使用LinkedList
C:如果涉及多线程安全问题,就使用Vector
(4)注意:ArrayList的contains方法底层依赖的是equals方法。
3:Object类的equals方法
一般,重写equals方法。因为默认的equals比较的是地址值,没什么意义。
一般重写的时候,判断的是对象的所有属性是否相同。
class Student
{
private String name;
private int age;
private String address;
public Student(){}
public Student(String name,int age)
{
this.name = name;
this.age = age;
}
//get/set省略
public boolean equals(Object obj)
{
//为了提高效率
if(this==obj)
{
return true;
}
//为了提高程序的健壮性
if(!(obj instanceof Student))
{
return false;
}
//向下转型
Student s = (Student)obj;
return this.name.eqauls(s.name) && this.age==s.age && this.address.equals(s.address);
}
}
4:Set
(1)set是一种无序无重复元素的Collection。
(2)Collection的体系结构
Collection
|--List 元素可以重复,有序
|--ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高。
|--Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低。
|--LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高。
|--Set 元素唯一,无序
|--HashSet
底层数据结构是哈希表。
如果保证元素的唯一性
它依赖于两个方法:hashCode和equals。
首先,判断哈希值是否相同,如果不同,就直接添加到集合中。
如果相同,在进入equals方法判断,
如果返回值是false,就添加进集合。
如果返回值是true,说明是重复元素,不添加到集合中。
|--TreeSet
底层数据结构是二叉树。
如果保证元素的唯一性
根据Comparable接口的compareTo方法或者Comparator接口的compare方法的返回值是否为0,
来确定是否是重复元素。如果是0,就不添加元素。
排序:
让元素本身具备比较性:Comparable -- compareTo
让集合具备比较性:Comparator -- compare
(3)HashSet 如何保证元素的唯一性
public class Student
{
private String name;
private int age;
public Student(){}
public Student(String name,int age)
{
this.name = name;
this.age = age;
}
//get/set...
public int hashCode()
{
return this.name.hashCode()+this.age*11;
}
public boolean equlas(Object obj)
{
if(this==obj)
{
return true;
}
if(!(obj instanceof Student))
{
return false;
}
Student s = (Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
}
public class HashSetDemo
{
public static void main(String[] args)
{
HashSet<Student> hs = new HashSet<Student>();
Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();
hs.add(s1);
hs.add(s2);
hs.add(s3);
//遍历
}
}
(4)TreeSet 如何保证元素的唯一性
public class Teacher
{
private String name;
private int age;
public Teacher(){}
public Teacher(String name,int age)
{
this.name = name;
this.age = age;
}
//get/set...
}
public class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet<Teacher> hs = new TreeSet<Teacher>(new Comparator<Teacher>(){
public int compare(Teacher t1,Teacher t2)
{
int num = t1.getAge()-t2.getAge();
int num2 = (num==0)?(t1.getName().compareTo(t2.getName()):num;
}
});
//添加元素,并遍历输出
}
}
5:总结
如果你使用的集合要保证元素唯一:Set
不需要排序:HashSet
需要排序:TreeSet
如果你使用的集合不用保证元素唯一:List
查询:ArrayList
修改:LinkedList
线程不安全:Vector
小技巧:
Array:说明底层数据结构是数组,查询快,增删慢
Link:说明底层数据结构是链表,查询慢,增删快
Hash:说明底层数据结构是哈希表,保证元素唯一,要依赖hashCode和equals。
Tree:说明底层数据结构是二叉树,有两种方案保证唯一和排序:
A:Comparable -- compareTo
B:Comparator -- compare
6:Map
(1)Map是存储键值对元素的顶层接口。
A:特点
双列的集合
数据时成对出现的
键是唯一的
B:和Collection的区别
Collection是单例的集合
数据是单个出现的
List的元素可重复,Set的元素是唯一的。
(2)Map的功能
A:添加元素
put(Object key,Object value):把键值对元素添加到Map集合中
B:删除元素
remove(Object key):删除键为key的元素
C:判断功能
containsKey(Object key):判断Map集合中是否有键为key的键值
containsValue(Object value):判断Map集合中是否有值为value的值
D:获取元素
get(Object key):根据键获取值
keySet():获取Map集合的键的Set集合
values():获取Map集合的值的Collection集合
entrySet():获取Map集合的键值对的集合
E:长度
size():Map集合中键值对元素的个数
遍历的思路:
思路1:
获取键值对的集合 keySet()
遍历键集合,获取到每个键 Iterator hasNext(),next()
通过键去找自己的值 get()
思路2:
键值对的映射项Map.Entry是Map做好的:
Map.Entry<Key,Value>
键值对集合 entrySet()
遍历键值对集合,获取到每个键值对的映射项Map.Entry对象 Iterator hasNext(),next()
通过键值对的映射项Map.Entry对象获取键和值 getKey(),getValue()
案例演示:
键和值都是字符串:
Map<String,String> map = new HashMap<String,String>();
map.put("张三", "北京");
map.put("李四", "上海");
map.put("王五", "天津");
map.put("赵六", "重庆");
map.put("田七", "陕西");
//方式1
Set<String> keySet = map.keySet();
Iterator<String> keyIt = keySet.iterator();
while(keyIt.hasNext())
{
String key = keyIt.next();
String value = map.get(key);
System.out.println(key+"***"+value);
}
//方式2
Set<Map.Entry<String,String>> meSet = map.entrySet();
Iterator<Map.Entry<String,String>> meIt = meSet.iterator();
while(meIt.hasNext())
{
Map.Entry<String,String> me = meIt.next();
String key = me.getKey();
String value = me.getValue();
System.out.println(key+"***"+value);
}
(3)HashMap
是如何保证键的唯一性:
通过自定义对象的hashCode方法和equals方法。
代码体现:键是自定义对象,值是字符串
前提:Student重写了hashCode方法和equals方法。
HashMap<Student,String> hm = new HashMap<Student,String>();
Student s1 = new Student("科比", 20);
Student s2 = new Student("霍华德", 22);
Student s3 = new Student("易建联", 25);
Student s4 = new Student("乔丹", 24);
Student s5 = new Student("林书豪", 23);
Student s6 = new Student("易建联", 25);
Student s7 = new Student("乔丹", 24);
hm.put(s1,"北京");
hm.put(s2,"上海");
hm.put(s3,"重庆");
hm.put(s4,"天津");
hm.put(s5,"武汉");
hm.put(s6,"深圳");
hm.put(s7,"石家庄");
//遍历
Set<Student> set = hm.keySet();
Iterator<Student> it = set.iterator();
while(it.hasNext())
{
Student key = it.next();
String value = hm.get(key);
System.out.println(key.getName()+"***"+key.getAge()+"***"+value);
}
(4)TreeMap
是如何保证键的唯一性和排序的:
集合具备比较性:Comparator -- compare
元素具备比较性:Comparable -- compareTo
(5)LinkedHashSet和LinkedHashMap
通过链表保证有序
通过哈希保证唯一
LinkedHashSet:保证元素有序,唯一
LinkedHashMap:保证键有序,唯一
(6)HashMap和Hashtable的区别:
A:Hashtable是线程安全的,效率低。HashMap是线程不安全的,效率高。
B:Hashtable的键和值都不能为null。HashMap可以允许null键和null值。
7:工具类的使用
(1)对数组操作的Arrays
A:static String toString(数组)
B:static void sort(数组)
可以对对象数组进行排序。
两种方式:
元素具备比较性
Arrays的sort方法具备比较性
C:static int binarySearch(数组,值)
前提:数组有序
D:static <T> List<T> asList(T... t)
(2)对集合操作的Collections
A:static void sort()
B:static void reverse()
C:static int binarySearch(集合,值)