集合
数组
作用
数组是一种容器,可以在其中放置一个或一组数据。从而,实现使用数组来管理一组数据。
优势
是一种简单的线性序列,可以快速的访问数组元素,效率高。如果从 效率和类型检查的角度 讲,数组是最 好的。
劣势
不灵活:容量事先定义好,不能随着需求的变化而扩容。
比如:我们在一个用户管理系统中,要把今天注册的所有用户取出来,那么这个用户有多少个?我们在 写程序时是无法确定的。如果,你能确定那你就是神了。因此,就不能使用数组。
从而看出,数组远远不能满足我们的需求。我们需要一种 灵活的 , 容量可以随时扩充的 容器来装载我们 的对象。这就是集合框架。
Collection接口
Collection是一个接口,只是规定了一些方法,即作为一个容器就应该具有这些功能。在Collection 中并没有任何的可以存储数据的地方,因此只是作为一个规范存在。
添加 add
删除 remove
记数 size
包含 contains
清空 clear
是否空 isEmpty
List extends Collection
List作为有序的Collection。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户 可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。同样是一个接口也只是 提供了一些抽象方法,做出相应的规范
可以存放很多数据,List中的数据可以重复
获取 get
查询对象出现的索引 indexOf(Object)
void add( Object element);
void add (int index, Object element);
Object get (int index);
Object set (int index,Object element);//修改某一位置的元素
Object remove (int index);
int indexOf (Object o);//返回某个元素的索引。如果没有该数据,返回-1
Set extends Collection
List作为Collection的子接口,也只是提供了一些抽象方法,做出相应的规范.
可以存放很多数据,但是set中的数据不能重复
如果前后数据重复,只存放一个
容器的使用
无论是何种容器使用步骤和方式都类似,首先需要有一个容器对象,然后再通过方法对容器中的数 据据进行增、删、改、查操作。各种操作的内部对用户都是透明的,我们只需要通过调用方法即可。
List
List接口下有两个实现类 LinkedList 和 ArrayList ,其中都实现了List中的方法,并且都给出了可 以存储数据的空间。
List遍历
普通for循环 ,利用List元素有下标的特点,依次获取每一个元素
for (int i=0; i<list.size(); i++){
System.out.println(list.get(i));
}
增强for 依次获取集合中每一个元素存入一个临时变量中
for (String temp : list) {
System.out.println(temp);
}
迭代器
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
底层用双向链表实现的List。特点:查询效率低,增删效率高,线程不安全。
底层用数组实现的List。特点:查询效率高,增删效率低,线程不安全。
Set
Set接口下有一个 HashSet 实现类,HashSet的底层是用 HashMap 实现的( 看了HashMap后再回来 看HashSet的实现 ),因此,查询效率高。由于采用Hashcode算法直接确定元素的内存地址,增删效率 也高。
HashSet 接口中的元素无序不可重复,不包含重复元素,最多包含一个 null,元素没有顺序 。
Set<String> set = new HashSet<>();
set.add("AAAA");
set.add("CCCC");
set.add("EEEE");
set.add("DDDD");
set.add("BBBB");
for (String s : set) {
System.out.println(s);
}
===================================================================
EEEE
AAAA
CCCC
DDDD
BBBB
无序
元素的存储顺序,不由存放顺序而定,容器有自己的一套存放顺序的规则。
遍历
普通for循环, 用不了,因为Set集合的元素是没有下标的,不可以通过下标获取
增强for
for(String s : set){
System.out.println(s);
}
迭代器
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
集合中存放自定义类型的数据
List: 有序的,元素可以重复
判断集合中是否包含一个指定对象的时候,是通过对象的 equals 方法进行比较的
Set: 无序的,元素是不重复的
添加元素之前,就已经经过了判断,判断当前集合中是否已经存在待添加的元素
collection.contains(Object),其实就是判断集合中是否有一个元素和给定的元素相等
先走 hashCode 方法,如果hashCode方法返回值相同,再走 equals 方法进一步比较
不可重复
按照以前的学习
基本数据类型比的是值
引用数据类型比得是地址
现在我们比较对象是否相等,更多的是考虑对象的逻辑上是否为同一个
对象内部属性的值是否相等
于是很多比较我们都使用equals方法进行比较
但是如果我们不进行重写,默认调用的是Object的,Object的equals比较的依然是地址
public boolean equals(Object obj) {
return (this == obj);
}
于是我们需要重写
equals 使用IDE生成,然后根据业务进行增减
如果这个对象有1000个属性,那么就要比较1000次,太麻烦了
于是提出先比较hashcode,然后再比较equals
因为hashcode就是由对象所有属性的值计算而来的
如果两个对象相等,那么hashcode也相等
只有hashcode相等了,再去比较equals,大大节省了对象比较的次数
两个对象不等也许hashcode也会相等
所以比较完hashcode之后,必须在比较equals
创建对象之后,一定要重写它的equals和hashcode方法
如果两个对象equals,hashcode一定相等
两个对象hashcode相等,但是不一定equals
Map
假如你的List中有8000个数据对象,我现在要从8000个数据对象中查找一条,问怎么查找最快? Map也是容器的一种,但是没有继承Collection接口,以键值对的形式存放数据,==一个key对应一 个value==。key和value都是引用数据类型,我们可以通过key找到对应的value Map类中存储的键-值对通过 键 来标识,所以 键值不能重复 。
Map接口
Map只是一个接口,其中提供了Map的规范,即各种方法的定义
Object put(Object key, Object value);
Object get(Object key);
Object remove(Object key);
boolean containsKey(Object key);
boolean containsValue(Object value);
int size();
boolean isEmpty();
void putAll(Map t);
void clear();
常见的实现类有 HashMap 、 HashTable 等
注意:如果存入的键值对中key相同,那么后面的会覆盖掉前面的当数据存放到Map之后,我们是无 法控制存放数据的顺序的
HashMap
HashMap作为Map的实现类,其中的方法都进行了实现,并且定义了可以存储数据的空间,其中使用了 一个叫做 Entry 的内部类,作为数据的存储
Map<String, String> map = new HashMap<>();
map.put("1","一,壹,Ⅰ");
map.put("2","二,贰,Ⅱ");
map.put("3","三,叁,Ⅲ");
System.out.println(map.get("1"));
HashMap中存储数据的特点:
存储的元素是以K-V的形式存在的
map集合中 key 必须要唯一,如果添加了相同的键值对(键相同)会发生覆盖
map集合中元素(键值对)是无序的,和Set集合类似
Map遍历
keySet
将所有的 key 获取存入 Set 集合中,遍历存储 key 的 Set 集合,结合 get(key) 方法可以获取 map 中每一个 key 以及对应的 value。
Set<String> keys = map.keySet();
// 增强for
for(String key : keys){
System.out.println(key + " - " + map.getKey(key));
}
// 迭代器
Iterator<String> it = keys.iterator();
while(it.hasNext()){
String key = it.next();
System.out.println(key + " - " + map.getKey(key));
}
values
将所有的 value 值获取后存入Collection集合中,遍历存储了所有 key 的集合,则可以获取到所有的 value 值,但此种方式只能获取到每一个value,并不能获取到key。
Collection<String> values = map.values();
// 增强for
for (String value : values) {
System.out.println(value);
}
// 迭代器
Iterator<String> it = values.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
EntrySet
将Map集合中的每一个键值对作为一个 Entry 对象获取到一个Set集合中,通过对象的 getKey 和 getValue 方法获取 key 和 value
Set<Map.Entry<String, String>> entries = map.entrySet();
// 增强for
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey() + "-" + entry.getValue());
}
// 迭代器
Iterator<Map.Entry<String, String>> it = entries.iterator();
while(it.hasNext()){
Map.Entry<String, String> entry = it.next();
System.out.println(entry.getKey() + "-" + entry.getValue());
}
无论是List还Set或者是Map都是集合,都是为了存储具有不同特征的数据,根据实际情况选择不同 的容器即可。
表象看集合里面数据的特征:
List(ArrayList,LinkedList):单个数据,数据是可以重复的,而且可以指定位置
Set:单个数据,数据是不可以重复,而且是无序的(不由用户来指定位置|顺序)
Map:成键值对的数据,数据是没有顺序的,键是不可以重复的
hashCode在Set和Map集合中判断对象是否重复(相同)
equals也是用来判断对象是否相同(重复)List,Set,Map
Properties
Properties为Hashtable的子类,要求键与值只能为字符串 ,不能为null,长与 配置文件(与外界交 互 的信息) 即内存与存储介质(文件、数据库、网络、服务器内存等)交互。
原来的集合(Set, List, Map) 都是内存中自己给数据,Peroperties 特殊在于,他自己去读取磁盘中文 件的内容,添加到集合中,直接使用有数据的集合即可(自己提供集合对象)。一般使用在配置文件中
Properties pro = new Properties();
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.
properties")); // 通过当前线程获取ClassLoader
System.out.println(pro.getProperty("userName"));
db.properties 配置文件
userName=zhangsan
userPwd=123
Collections工具类
类 java.util.Collections 提供了对Set、List、Map操作的工具方法。
void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。
void shuffle(List) //对List容器内的元素进行随机排列
void reverse(List) //对List容器内的元素进行逆续排列
void fill(List, Object) //用一个特定的对象重写整个List容器
int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象
Comparable接口
所有可以“排序”的类都实现了 java.lang.Comparable 接口, Comparable 接口中只有一个方法 public int compareTo(Object obj)
返回 0 表示 this == obj ;
返回正数表示 this > obj ;
返回负数表示 this < obj 。
实现了Comparable 接口的类通过实现 comparaTo 方法从而确定该类对象的排序方式。
public class TestComparable {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
Student stu1 = new Student(1,"张三",100);
Student stu2 = new Student(2,"张四",80);
Student stu3 = new Student(3,"张五",90);
list.add(stu1);
list.add(stu2);
list.add(stu3);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
class Student implements Comparable<Student> {
int id;
String name;
int score;
public Student(int id, String name, int score) {
super();
this.id = id;
this.name = name;
this.score = score;
}
public String toString(){
return name+score;
}
@Override
public int compareTo(Student o) {
if(this.score>o.score){
return 1;
}else if(this.score<o.score){
return -1;
}else {
return 0;
}
}
}
Comparator 接口
Comparator比较器,可以根据需要定制特定的比较规则
List<Student> stus = new ArrayList<Student>(){
{
add(new Student("张三", 30));
add(new Student("李四", 20));
add(new Student("王五", 60));
}
};
//对users按年龄进行排序
Collections.sort(stus, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 升序
//return s1.getAge()-s2.getAge();
return s1.getAge().compareTo(s2.getAge());
// 降序
// return s2.getAge()-s1.getAge();
// return s2.getAge().compareTo(s1.getAge());
}
})