概述
- 在之前的学习中遇到多个变量,我们是使用数组进行存储
- 数组在创建的时候就需要指定长度
- 由于数组的长度不可以变,不可以新增,数组在扩容/缩容的时候需要创建一个新的数组
- 集合概念和数组类似,也是可以存储多个引用变量
- 集合的长度是可以变的
- 集合还提供了格式排序,比较等等方法,方便用户对集合的操作
- 集合本质上是数组的封装类,本质上最终存储数据还是数组
- 根据不同的数据结构,集合可以分为以下几类
- List
- Set
- Map
- List:线性有序的集合
2. Set:无序的集合
3. Map:使用key/value的方法进行存储
List有序集合
- List在java是一个接口, 它父类是Collection,它有各种不同的底层实现
- ArrayList
- LinkedList
- Vector
ArrayList的基本使用
集合的创建,新增,获取 和删除
ArrayList list = new ArrayList();
//给集合中放入对象
list.add(1); //0
list.add("aa");//1
list.add(true);//2
list.add(new Student("小王",15));
//获取数据
Integer i = (Integer) list.get(0);
String aa = (String) list.get(1);
Boolean flag = (Boolean) list.get(2);
Student student = (Student) list.get(3);
list.remove(2);//删除
System.out.println(i);
System.out.println(aa);
System.out.println(flag);
System.out.println(student.toString());
集合的遍历
//第一种遍历集合的方式
for (int j=0;j<list.size();j++){
System.out.println(list.get(j));
}
//第二种遍历的方式
System.out.println("第一个遍历的方式:");
//类型 一个对象的变量 : 集合的遍历
for (Object obj :list) {
System.out.println(obj);
}
//第三种方式lambda表达式
list.forEach(obj->{
System.out.println(obj);
});
泛型
List有三种中实现,都是继承的List接口只是在实现上不同,在使用上是一摸一样的
- LinkedList是通过链表,删除和新增的速度快查询慢
- ArrayList是查询快,删除和新增慢
- Vector都慢,但是线程安全
所以在使用的时候,都会直接使用List指向三种不同类型的集合
List list = new ArrayList();
List linkedList = new LinkedList();
在list的add 和 get方法,是不需要设置类型的
- 在添加虽然可以放入不同的数据类型
- 但是在获取结果的时候需要强制类型转换,就会影响程序的速度
- 可以通过泛型解决这个问题
泛型指的是可以将集合中的数据定义成指定的类型,在获取结果的时候不需要强制类型转换
List<Integer> list = new ArrayList();
//List linkedList = new LinkedList();
list.add(1);//只能存放Integer类型
//list.add("a");
Integer i = list.get(0);//获取数据的不需要进行类型转换
泛型的定义
reverse实现集合的反转
- shuffle:随机重置
sort:可以进行排序
- 默认情况下是直接使用升序
- 如果需要使用降序,请重写Comparator接口
Collections.sort(list, new Comparator<Integer>() {
//实现比较的规则
@Override
public int compare(Integer o1, Integer o2) {
if(o1>o2){
return -1;
}else if(o1<o2){
return 1;
}
return 0;
}
});
binarySearch:使用二分查询,查找对应的值的下标
将一组对象,直接放入到集合中,默认情况下没有顺序概念,不能插入相同的元素
一般添加元素
//创建对象
Book b1 = new Book("天龙八部","金庸",98);
Book b2 = new Book("神雕侠侣","金庸",78);
Book b3 = new Book("背影","朱自清",18);
//创建集合
Set<Book> set = new HashSet<>();
//将对象放入到集合中
set.add(b1);
set.add(b2);
set.add(b3);
遍历集合
//遍历集合查询
//增强foreach
/*
for (Book book :set) {
System.out.println(book.toString());
}*/
//使用lambda表达式
/*
set.forEach(book -> {
System.out.println(book.toString());
});*/
//使用迭代器
Iterator<Book> iterable = set.iterator();
//循环迭代
while(iterable.hasNext()){
Book book = iterable.next();
System.out.println(book.toString());
}
三种实现
- HashSet:底层直接使用HashMap进行实现的,
- 在长度超过一定数量的时候,会进行数据重排
- 主要是通过hashCode定义元素的插入位置
- 在判断两个元素是否一致的时候,需要重写hashCode和equals两个方法
- LinkedHashSet:由于底层主要是通过链表实现的,没有扩容的问题,
- 会保证插入的顺序是不变的
- TreeSet:底层是通过tree实现的
- Collections的sort只对list有效,如果要使用排序则要使用TreeSet
- 插入的对象需要实现Comparable接口才行
- 在重写Comparable接口的时候,如果返回的结果是0,那么元素就不会被插入了
- HashSet:底层直接使用HashMap进行实现的,
equals和hashcode的区别
通过key将对应的值放入到集合中,在集合中主要是通过key定义元素的位置
Map map = new HashMap();
//放入值
map.put(1,"小明");
//获取值
Object result = map.get(1);
System.out.println("result="+result);
map.put("a","小明");
map.put("a","小黑");
Object rs = map.get("a");
System.out.println("a的值:"+rs);
HashMap存储的最小的单位是一个Entry(其中包括了key和Value)
public static void main(String[] args) {
Map<Integer, Student> map = new HashMap<>();
for(int i=0;i<5;i++){
map.put(i,new Student("学生"+i,1+i));
}
//第一种,通过EntrySet遍历
//获取map中所有的entry
Set<Map.Entry<Integer,Student>> entrySet = map.entrySet();
//遍历存储了所有的entry的Set
for (Map.Entry<Integer, Student> entry :map.entrySet()) {
//获取Entry的key值
Integer key = entry.getKey();
//获取Entry具体存储的值
Student s = entry.getValue();
System.out.println(key+":"+s.getName());
}
//第二种通过遍历keySet获取值
for (Integer key : map.keySet()) {
//通过key获取值
Student value = map.get(key);
System.out.println(key+":"+value.getName());
}
//第三种使用lambda表达式
map.forEach((key,value)->{
System.out.println(key+":"+value.getName());
});
}
Map的实现
- HashMap:基本实现,使用key-value形式对数据进行存储,并且是在Hashtable的基础上进行了优化,速度很快,但是线程不安全,需要使用ConcurrentHashMap保证线程的安全
TreeMap:可以对key值进行排序
- 所以key的类需要实现Comparable
```java
public class MyKey implements Comparable
{ String key;
public MyKey(String key) { this.key = key; }
public String getKey() { return key; }
public void setKey(String key) { this.key = key; }
@Override public int compareTo(MyKey o) { Integer keyValue = Integer.parseInt(o.getKey());
return Integer.parseInt(this.key)-keyValue; }
@Override public String toString() { return “MyKey{“ +
"key='" + key + '\'' +
'}';
} } ```
- 所以key的类需要实现Comparable
```java
public class MyKey implements Comparable
Properties也是map的实现,可以直接从文本文件中通过key读取其相关的值
创建一个properties文件,以key=value的形式存储数据
name=小明
password=123
通过代码加载文件,读取数据
Properties ps = new Properties();
//加载properties的文件
ps.load(TestMap004.class.getResourceAsStream("info.properties"));
//通过key将properties文件中的值进行获取
String name = ps.getProperty("name");
String pwd = ps.getProperty("password");
System.out.println(name+":"+pwd);