首先说一下集合的由来:
java中我们存储比较大量的数据的时候,我们一般用的是数组,但是有一种一下几种情况我们使用数组的话就比较麻烦了:
1.当我们不知道我们的数据到底有多少的时候,(一般我们会数值一个比较大的数组这样就造成了内存的浪费)
2.当我们向一个满的数组继续放入数据的时候,会出现越界问题,如果想继续存入我们必须将这个数组拷贝到一个更大的数组中。因此java中定义了集合,集合最最基本的特点就是:可以自动增加。当然集合还有其他特点。
集合的几个类型:list,set,map主要的就这三个。
集合和数组的区别:
1. 数组可以存储基本数据类型,也可以存储应用数据类型,存储基本数据类型的时候存储的是值,存储引用数据类型的时候存储的是地址值;
集合只能存储引用数据类型,(当存储基本数据类型的时候他会自动装箱比如int--->Integer char --->Character.....)
2. 数组长度不可变,而且存储数据的时候类型在定义的时候已经限制了
集合长度可变,而且因为所有的引用数据类型都有一个父类(object)因此集合可以放入多种引用数据类型。
各种集合继承关系:
这一点要注意,虽然都是集合但是他们的底层是不一样的。
下面开始了解一下List:
List的定义:标准的定义是 List<E> list=new List的子类<>(); (E表示list里面放的类型,就行数组前面的类型一样,注意这里不能写int这些只能写Integer) 当然亦可以不写E List list=new Lis的子类t();那么他会默认E=object
List子类共有的方法:
set(int index, E element)//在指定位置增加元素
boolean add(E e) //增加元素 boolean remove(Object o) //删除元素 void clear() //清空 boolean contains(Object o)//!!很有用的一个函数,可以确定一个元素是否在集合中存在 boolean isEmpty() //判断是否没空 int size() //打到尺寸
当然还有其他方法,可以看API
接下来说说各个集合的特点吧,先来介绍List的各个子类:
ArrayList: 最常用的一个子类,里面的数据可以重复怎么存入就怎么读写。底层的数据结构是数组,查询快,增删慢,线程不安全,效率高。
Vector: 底层也是数组,查询快,增删慢。线程安全,效率低;
LinkedList: 底层数据结构是链表,查询慢,增删快。线程不安全,效率高。这个一般不经常用。只用于大量数据增删的情况。
来解释一下线程不安全的与线程安全的大致意思吧:
假设这里有一种场景,有一个ArrayList(),然后有两个并行的线程同时对这个List进行操作,那么就会出现一种情况,线程A删了一个元素,这时候线程B想知道这个List大小的时候,就会出现问题,或许线程B中的List还没有更新,这样就导致了错误,这就是线程不安全,而Vector理论上是线程安全的。(实际上并不是的,还是会出现并发异常的问题.....怎么体现Vector并不是很安全参见https://blog.csdn.net/zlp1992/article/details/50433778)
然后介绍一些LinkedList中的一些特有方法。
* public void addFirst(E e)及addLast(E e) //在开头或者结尾增加元素 * public E getFirst()及getLast() //得到开头、结尾 * public E removeFirst()及public E removeLast() //移除开头或者结尾
因为LinkedList的底层是链表,因此很容易定位到开头和结尾
集合的第二大类:Set
set相比于list的不同:
1.list是有序的,set是无序的。即list会根据你的输入打印,打算set不会。
2.list可以放入重复的元素,但是set不能。----这也是他无序的原因,他将每个元素赋予了一个哈希值这样就保证了元素的不重复。
(但是有一点要注意,他不能比较两个类是否相同)
比如:我们又一个类 Person( name,age) 要放入set中
HashSet<Person> hs = new HashSet<>(); hs.add(new Person("张三", 23)); hs.add(new Person("张三", 23));
这样两个Person都会放入,尽管我们认为这两个类是一样的,但是hashCode函数并不会认为他们是同一个对象,因此还是都会存入set,这时候我们必须重写hashCode函数和equal()函数:
为了加深理解我们用代码解释一下:
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 int hashCode() { System.out.println("asdasd"); final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { System.out.println("2112"); if (this == obj) //调用的对象和传入的对象是同一个对象 return true; //直接返回true if (obj == null) //传入的对象为null return false; //返回false if (getClass() != obj.getClass()) //判断两个对象对应的字节码文件是否是同一个字节码 return false; //如果不是直接返回false Person other = (Person) obj; //向下转型 if (age != other.age) //调用对象的年龄不等于传入对象的年龄 return false; //返回false if (name == null) { //调用对象的姓名为null if (other.name != null) //传入对象的姓名不为null return false; //返回false } else if (!name.equals(other.name)) //调用对象的姓名不等于传入对象的姓名 return false; //返回false return true; //返回true } }
这里有一个Person类
public class Demo1_HashSet { /** * @param args * Set集合,无索引,不可以重复,无序(存取不一致) */ public static void main(String[] args) { //demo1(); HashSet<Person> hs = new HashSet<>(); hs.add(new Person("张三", 23)); hs.add(new Person("张三", 23)); hs.add(new Person("李四", 24)); hs.add(new Person("李四", 24)); hs.add(new Person("李四", 24)); hs.add(new Person("李四", 24)); //System.out.println(hs.size()); System.out.println(hs);
} }
重写hashCode函数是防止出现重名的对象;重写equals函数可以防止真的对象的重复,注释已经很详细了我就不在解释了。
然后是
LinkedHashSet:
因为set是无序的为了解决这个缺点我们使用了linkeHashSet,大家都知道链表是有序的,所以这个集合是有序切不能重复的。这个特点可以用来去除重复,比如“aaabbssdd”最后存进去的可以变成absd;
然后是最后一个TreeSet;
他的底层也有哈希函数,但是多了一个树!!那么他就有了一个新的特性,就是会自动排序,底层会很久哈希值对所有的元素排序。
当然:如果想认为的设置这个的顺序,需要重写compareTo函数,为什么会出现这样的情况呢?还是由于之前的问题,对于我们自定义的对象,他不会排序。
在比较的时候他会调用compareTo函数,这个函数返回值为 -1 0 1 :也就是小于等于大于。当返回1的时候就放在左节点,返回-1的时候就放在右节点;因此才会排序;