集合的介绍与比较器的应用
1.集合:
是一种容器,一种变量类型,跟数组很像
数组的缺点:
A.数组的空间长度固定,一旦确定不可以更改。多了浪费,少了报错。
B.使用数组 操作数据的时候,【删除,增加】效率比较低。
C.没办法获得数组中存储的真实元素个数。
D.数组没办法满足,无序,不可重复的数据满足不了。
以上集合都可以满足。
2.集合的分类:
根据存储数据的方式:
Collection(一个一个存储元素,无序 不唯一)
list(不唯一,有序)
set(无序,唯一)
最后一排为实现类,上两排为接口,不能new 接口,但可以new 它的实现类
map(一对一对存储元素 key 无序唯一 -value 无序不唯一)
HashMap和TreeMap为类,是实现Map接口的类,HashTable是老版本,更安全,但效率更低
3.介绍Collection接口:
Collection 接口:不唯一 无序的元素。
> 添加:add(23);addAll(c);
> 删除:remove(23);removeAll(c1);clear();
> 判断:contains(“张三”);isEmpty();
> 查找:size();iterator();
> 转换:toArray();
4.介绍Iterator接口:
迭代器:“Iterator就是为循环遍历集合而生的”
Iterator iterator = c.iterator();
//c对象调用方法,获得一个能遍历自己的迭代器。
while(iterator.hasNext()){//
System.out.println(iterator.next());
}
针对不同的对象,设计不同的遍历器,比如这里是c,如创建了d,则使用d.iterator()方法
5.介绍List接口:
List 有序 不唯一的元素:
* 添加: add(0,"bb");addAll(0,list);
* 删除:remove(2);
* 修改:set(0,"cc");
* 判断:
* 查找:get(0);indexOf("张三");
* 转换:
* 排序:sort();【排序】
ArrayList和LinkedList的区别在于底层原理不同:一个是数组,一个是链表
6.介绍ArrayList实现类
【没有自己特有的方法】
- ArrayList 底层就是Object[]数组,数组空间大小初始值是10;
- 以1.5倍的空间大小扩增。
- 优势:随机访问,和遍历的效率高!缺点:删除 和 添加的效率低!
- Vector VS ArrayList
A.语法上一样的。
B.区别:
Vector jdk版本1.5之前
ArrayList jdk版本1.5之后
Vector 线程安全的,速度慢,效率低。
ArrayList 线程不安全的,速度块,效率高。
Vector 底层数组以2倍速度扩充空间大小;
ArrayList 底层数组以1.5倍速度扩充空间大小;
7.介绍LinkedList实现类:
存储(下标) 有序 不唯一的元素
LinkedList:底层是Linked链表结构。
优点:擅长做 删除,添加操作
缺点:查找,随机访问效率低。
LinkedList 有序 不唯一的元素:
* 添加: addFirst(12D);addLast(90.9);
* 删除:removeFirst();removeLast();
8.介绍Set接口:
无序 唯一的元素
没有自己特有的方法。只有Collection父接口里的方法
9.介绍HashSet实现类:
无序 唯一的元素
介绍HashSet去重原理:借助元素对象的两个方法,HashCode(),equals().
- 首先使用HashCode()获得要存入元素的hash值
- 依次比较集合中已有的元素hash值
- 如果hash值不同,直接将该元素存入集合。
- 如何hash值相同的,再使用equals() 继续进行两个hash值相同的对象的属性比较。
- 如果属性都相同,拒绝存入集合中。
- 如果属性不相同,可以存入集合中。
hashSet集合存储的元素,
要对HashCode() 和 equals() 进行重写。
改为关注属性是否相同而不是内存地址。
10.介绍TreeSet实现:
有序(排序) 唯一的元素
介绍TreeSet去重原理:利用比较器的比较方法。
将要存入的元素与以存入的元素依次比较。
如果比较的结果为0,则认为是相同元素,拒绝存入。
如果比较的结构是1,则认为是不同元素,可以存入,并且位置靠前。
如果比较的结构是==-1==,则认为是不同元素,可以存入,并且位置靠后。
示例
TreeSet<String> set2=new TreeSet();
set2.add("asd");
set2.add("asdf");
set2.add("abc");
set2.add("bc");
set2.add("aaaaaaaa");
set2.add("bc");
System.out.println(set2);
结果如图:
引用型变量的比较
TreeSet<Student> stus=new TreeSet<>();
stus.add(new Student(1, "张三c", 23, "男"));
stus.add(new Student(2, "李四w", 24, "女"));
stus.add(new Student(4, "张三c", 23, "男"));
stus.add(new Student(3, "张三", 23, "男"));
stus.add(new Student(2, "李四s", 24, "女"));
stus.add(new Student(5, "张三d", 23, "男"));
System.out.println(stus.size());
报错:不具有比较能力
【如何让自定义类对象,拥有比较的能力?使该类实现Comparable接口,重写比较方法】
@Override
public int compareTo(Student o) {
if(stuId>o.stuId){
return 1;
} else if (stuId < o.stuId) {
return -1;
}else{
return 0;
}
}
如果要按照姓名来比较呢?上面的函数里直接返回
return stuName.compareTo(o.stuName);
字符串类型已经重写了compareTo方法,因此可以直接用。
11.介绍比较器:
比较器对象分为两种:内部比较器:实现Comparable接口,重写compareTo()方法。
- 缺点:
1.每次更改比较规则的时候,都要修改源码。
2.只有实现了内部比较器接口的对象,才可以存入TreeSet集合里。
外部比较器:
外部比较器 Comparator 方法:compare
内部比较器 comparable 方法:compareTo
使用步骤:
a.创建一个比较器类
b.重写compare()方法
import java.util.Comparator;
/**
* 创建一个外部比较器类:
* 比较规则:按照年龄进行排序和去重
*/
public class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return Integer.compare(o1.getAge(), o2.getAge());
}
}
外部比较器的使用
public class TreeSetTest {
public static void main(String[] args) {
AgeComparator age=new AgeComparator();
TreeSet<Student> stus = new TreeSet<>(age);
//意思是按照age来去重
stus.add(new Student(1, "张三c", 23, "男"));
stus.add(new Student(2, "李四w", 24, "女"));
stus.add(new Student(4, "张三c", 23, "男"));
stus.add(new Student(3, "张三", 23, "男"));
stus.add(new Student(2, "李四s", 24, "女"));
stus.add(new Student(5, "张三d", 23, "男"));
System.out.println(stus.size());
System.out.println(stus);
}
}
注意:外部比较器使用的时候需要传参,如:
TreeSet<Student> stus = new TreeSet<>(age);
内部比较器则不需要。
12.介绍Map接口:
Map 一对一对,以键值对key-value形式进行元素存储。
key 无序唯一的
value 无序不唯一的
解释:键值对形式更符合网络发展的适用场合。
public class HashMapTest {
public static void main(String[] args) {
Map<Integer,Student> map=new HashMap<>();
//只管key重复
Student stu1 = new Student(1, "张三c", 23, "男");
Student stu2 = new Student(2, "李四w", 24, "女");
Student stu3 = new Student(1, "张三c", 23, "男");
Student stu4 = new Student(4, "张三", 23, "男");
Student stu5 = new Student(5, "李四s", 24, "女");
Student stu6 = new Student(6, "张三d", 23, "男");
map.put(stu1.getStuId(), stu1);
//调用一次put方法,比较一次key值
map.put(stu2.getStuId(), stu2);
map.put(stu3.getStuId(), stu3);
map.put(stu4.getStuId(), stu4);
map.put(stu5.getStuId(), stu5);
map.put(stu6.getStuId(), stu6);
System.out.println(map);
}
}
不需要再重写hashCode和equals了,因为比较的key,key可以是String ,int …一定都已经重写了。
Student student = map.get(3);
student.setStuName("学生三");
put:存数据
get根据key取value
后存入的相同key值的数会将原有的值覆盖掉
Student stu6 = new Student(6, "张三d", 23, "男");
Student stu7 = new Student(6, "菲菲", 23, "男");
map.put(stu6.getStuId(), stu6);
map.put(stu6.getStuId(), stu7);
``
遍历Map集合的四种方式
第一种
System.out.println("第一种遍历Map集合的方式:");
Collection<Student> values = map.values();
//所有value值进行汇总存到valuse里
Iterator<Student> iterator=values.iterator();
while (iterator.hasNext()) {
Student stu=iterator.next();
System.out.println(stu);
}
第二种
System.out.println("第二种遍历Map集合的方式");
Set<Integer> integers = map.keySet();
//方法:汇总Map中所有的key值,形成集合
Iterator<Integer> iterator1=integers.iterator();
while (iterator1.hasNext()) { //判断迭代器指针下面是否还有元素
Integer key = iterator1.next();//如果有元素,那么向下取值,该值就是key值
Student stu = map.get(key);//通过get方法,,通过key值获得value值
System.out.println(stu); //输出value(底层调用toString)
}
第三种
System.out.println("第三种遍历Map集合的方式");
Set<Map.Entry<Integer, Student>> entries = map.entrySet();
//汇总键值对
Iterator<Map.Entry<Integer, Student>> iterator2 = entries.iterator();
while (iterator2.hasNext()) {
Map.Entry<Integer, Student> entry = iterator2.next();
Student stu = entry.getValue();
System.out.println(stu);
}
第四种
System.out.println("第四种遍历Map集合的方式");
Collection<Student> values2 = map.values();
for (Student stu : values2) { //增强型for循环
System.out.println(stu);
}
- 普通的for循环:必须要知道下标。
- 增强型for循环:可以在不知道下标的情况下,遍历集合/数组
for(集合中元素的类型 代号 :要遍历的那个集合/数组){
操作代号----操作对象
}
13.介绍HashMap
HashMap 是无序的,key不可重复
HashMap 如果put两个相同的key的键值对,后一个执行的会覆盖前一个
HashMap的键和值都可以为null
保证key值唯一的原理是:key类型要求重写hashCode()+equals()
14.介绍HashTable 和HashMap
a.HashTable 继承于Dictionary类;HashMap继承于 AbstractMap类
b.HashMap是线程不安全的,操作速度块,效率高, jdk新版本
Hashtable是线程安全的,操作速度慢,效率低 jdk老版本
c.对键值的要求不同,HashMap允许为空,Hashtable不允许为空。
d.默认初始容量不同:Hashtable是11,HashMap是16
15.介绍TreeMap 实现类 和 HashMap的区别:
a.key值去重的原理不同
b.底层存储数据的实现不同,hash表(数组+list集合) ,红黑数
c.TreeMap 的key是可以去重+排序的,HashMap的key 不能排序,只能去重。
16.介绍Properties类
“万事万物皆对象”
Java中有一种配置文件是以properties拓展名结尾的,
properties配置文件是以键值对形式存在的。
Java为这种配置文件提供了一个处理的类,
Properties类就是用来处理properties文件的。
它是Hashtable的子类,Hashtable中的方法可以用
但是因为它有自己独立的含义,所以大多数情况都不会用Hashtable中的方法,用它自己的方法。
原文地址:https://blog.csdn.net/weixin_47510148/article/details/143810055
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!