JAVASE总结--集合

来源:互联网 发布:matlab矩阵归一化函数 编辑:程序博客网 时间:2024/06/06 02:49

java中万事万物皆对象。所以容器也是对象。

首先将容器抽象成一个接口collection,它里面有两个比较重要的子接口:

list 和 set。

list和set有自己的子实现类。

类是用来存放任意类型的数据,而容器只能存放引用类型的数据(泛型)

collection是容器的根接口,提供了好多容器访问的方式,其中容器中每一个值都被称为元素。

java中,绝大部分容器都是由数组来实现的,极个别由链表和树来实现。

容器的底层就是一个数组,Object[],它什么都可以放

每当容器中数组容量不够的时候,就会自动扩容,扩容时创建新数组,并将之前的数据拷贝,大小为之前的1.5倍。

_______________________________________________

collection(接口)

list(接口)数据对象有顺序且可以重复

ArrayList(动态增长和缩减的索引序列)

LinkedList(可以在任何位置进行高效的插入和删除操作的有序序列)

set(接口)数据对象没有顺序且不可重复

HashSet(没有重复元素的无序集合)

Map(接口) key-value键值对

_______________________________________________

//创建一个容器对象

Collection c1=new ArrayList();

Collection只是接口不能实例化对象,只能通过子类来实例。

========================================================================

 

Collection常用方法

add-------------添加

c1.add("bj01");

c1.add("bj02");

c1.add("bj03");

addAll------------添加

Collection c2=new ArrayList();

c2.add("bj01");

c1.addAll(c2);

clear-----------------清空数据将数组长度变为0

c1.clear();

remove-------如果存在,移除单个元素

removeAll-------如果存在,移除整个指定collection在此的数据

contains---------------------包含

c1.contains("bj01");//true

containsAll------------------包含

c1.containsAll(c2);//true

retainAll-------取出两个容器的交集

size------------返回当前容器的元素数

hashCode------------返回此collection的哈希码值

toArray-----以正确顺序返回包含此列表中所有元素的数组。(见下)

isEmpty----------当前collection是否有数据

equals------------------逻辑相等

ArrayList中找不到equals时,去父类AbstractList中查找。源码如下:

    public boolean equals(Objecto) {

        if (o ==this)//引用同一个对象---true

            return true;

        if (!(o instanceof List))//o不是List的对象---返回false

            return false;

        ListIterator<E>e1 = listIterator();//迭代器e1

        ListIterator<?>e2 = ((List<?>)o).listIterator();//迭代器e2

        while (e1.hasNext() &&e2.hasNext()) {//遍历

            E o1 = e1.next();

            Object o2 = e2.next();

            if (!(o1==null ?o2==null :o1.equals(o2)))//( 如果o1不为空且o1.equals(o2) 或者o1为空、o2为空) 否则返回false

                return false;

        }

        return !(e1.hasNext() ||e2.hasNext());

    }

x? y:z  x是一个boolean类型,若x为true,结果显示y,若x为false,则结果显示z.

toArray

  c1.toArray(array);

System.out.println(c1.toString());

for(int i=0;i<array.length;i++){

System.out.println(array[i]);

}

 

虽然容器只能存储引用数据类型,但是存入基本数据类型不会出错,是因为自动装箱。

例如:

collection.add(new Integer(1));

collection.remove(1);

容器也可以存储自定义对象。但是一定要重写 toString、equals、hashCode。

toString

快捷键为:Shift+Alt+S  +S

object:打印出来的就是当前类的信息@地址信息的hash值

vo类中:打印出来当前类所包含所有属性的信息

equals

快捷键为:Shift+Alt+S  +H

object:两个对象比较的是地址,强调的是物理地址的相等,相当于==

普通对象中:两个对象逻辑上是否相等,比较的是两个对象的属性

hashCode

一个对象会有一个唯一的hash值,然后不同对象hash值相等的概率几乎为0

使用快捷键生成的方法一般不会出现问题。

代码:

public class Student {

private Stringsname;

private Stringgender;

private Stringidnumber;

private int age;

public Student() {

}

public Student(Stringsname, Stringgender, Stringidnumber, int age) {

this.sname =sname;

this.gender =gender;

this.idnumber =idnumber;

this.age =age;

}

}

/****************自定义对象*******************/

Student s1 =new Student("zhangsan","1", "999", 18);

Student s2 =new Student("zhangsan","1", "999", 18);

collection.add(s1);

collection.remove(s2);

源码:

add

//真正保存数据的数组

 private transient Object[] elementData;  //arrayList的实际元素数量

 private int size;

首先确定这个容器是不是空的,是的话将大小定为10.

同时将内容存至实际存储的元素数量的位置,之后size+1。

remove

输入字符串,判断输入的是否为空字符串,

是的话,遍历,找到值为空的,快速删除,size-1

不是的话,遍历找到与其逻辑地址相等的值,快速删除,size-1

========================================================================

List

常用方法:(以及collection的方法)

add(index,Object)-----将内容插入到指定的位置,后面的全体向后移

get-----获取指定位置的值

set----覆盖掉指定位置的原来的值

indexOf-----查看是否包含输入的内容

remove(index,Object)---将指定位置的值删除

输入下标,首先检查传入的下标是否越界,将数组从删除位后一位开始到拷贝到删除位置,之后size-1

========================================================================

* ArrayList

底层代码分析:

 * 成员变量

 * private int size;

 *   默认初始化为0

 * private Object[] elementData;

 *  list内部有一个私有的数组,而且这个数组只能装引用类型

 * 这个对象什么类型的数据都可以存放

 * 创建对象的时候,直接给成员变量赋值了一个空数组

 * this.elementData = EMPTY_ELEMENTDATA;

 *

 * 为什么api上面说构造一个初始容量为 10的空列表。

 * JDK5的时候创建数组长度默认为10

 * JDK7的时候创建数组长度为0,而且不管创建再多的arrayList,其实就是一个对象

 *当我们添加数据的时候

 * ensureCapacityInternal(size+1);

 * 当我们第一次使用的时候,默认创建一个大小为10的数组

 * elementData[size++] = e;

 * size位置存放数据,并且size自增,size存放的是当前数组的实际长度

 * 当数组的长度不满足当前需求的时候,每次就会扩容1/2

 * 当我们删除数据的时候

 * 循环比例数据,如果知道equals的,获取当前数据的索引,让数组后面的数据整体前移

 * 并且将最后一个数据赋值为null

 * size就是实际存放数据的多少

 * 当我们调用数组长度方法的时候,直接返回size

 * get方法的原理

 * elementData[index]

 * remove的时候

 * 获取当前数据的索引,让数组后面的数据整体前移

 * 并且将最后一个数据赋值为null

 

版本差异

1.5的时候,创建数据每次都创建一个长度为10的数组

1.7的时候,每次都指向同一个静态空数组。

========================================================================

LinkedList

* 链表

 * 在内存中是不连续的空间,直接通过节点的nextprevious属性访问

 * 链表添加数据就是添加Node节点,让节点的nextprevious分别指向对应的节点

 * 所以连接表的插入和删除操作比较快捷

 * 链表只记录一个开始和结尾  firstlast

 *

 * 数组

 * 在内存中是连续的空间,可以按照索引访问

 * 支持随机访问

 * 所以数据的getindex)速度较快

 *创建对象

 * 直接创建一个空对象

 * int size = 0;

 * Node first = null;

 * Node last = null;

 * add新增数据

 * 默认将数据拼接到链表的末尾

 * 创建一个新节点,新节点指向上个节点,原来的最后一个节点指向新节点,last指向新节点

 * remove删除数据

 * 根据索引遍历数据,只需要遍历链表的一 

 * 获取到指定节点

 * 根据节点的位置改变pre next first last的指向

 * set修改数据

 * 循环到指定的节点

 * 修改值

 * get查询数据

 * 循环到指定的节点,返回节点数据

 *get方法做了微小的优化,如果索引大于size()/2就从列表尾端开始搜索信息的操作。

 

 

 

 

========================================================================

 

collections工具类(类似于Arrays)

java.utils包下

//填充List

Collections.fill(list, "bjsxt");

//返回最大值和最小值

System.out.println(Collections.max(list));

System.out.println(Collections.min(list));

//替换指定元素

Collections.replaceAll(list, "bjsxt", "sxtly");

//逆序

Collections.reverse(list);

//随机排序

Collections.shuffle(list);

Collections.shuffle(list, new Random());

//排序

Collections.sort(list);

Collections.reverse(list);

//折半查找折半查找的前提是有序

Collections.sort(list);

System.out.println(Collections.binarySearch(list, "bjsxt9"));

========================================================================

 

遍历List

//声明并初始化了一个List

List<String>list = new ArrayList<String>();

for (int i = 0; i < 20;i++) {

list.add("bjsxt" +i);

}

List<String>linked = new LinkedList<String>();

for (int i = 0; i < 20;i++) {

linked.add("bjsxt" +i);

}

 *第一种方式for

//第一种遍历方式(当我们要使用索引值的时候,必须使用第一种)

for (int i = 0; i < list.size(); i++) {

System.out.println("list中的第" + (i + 1) + "个元素的值为:" + list.get(i));

}

 * 第二种方式增强for循环

//第二种方式(如果只需要获取list中的值,效率较高)

for (String string : list) {

System.out.println(string);

}

 * 迭代器

 * Iterator(通过光标/游标对数据进行访问的一种方式)

 * hasNext

 * 判断当前光标位置是否有数据

 * next

 * 取出当前位置的数据,并且光标向后移动一位

 * 使用的时候需要注意不要随意的去调用next方法,会导致跳过部分内容

 * 在使用next的时候我们必须要保证hasNext返回true

 

//第三种容器自带的迭代器

Iterator<String>iterator = list.iterator();

//开始遍历

while (iterator.hasNext()) {

String string =iterator.next();

System.out.println(string);

}

return iterator;

}

========================================================================

Map

 * Map是一个键值对结构的数据类型

 * key:我们要通过key去找我们对应的值

 * value:我们存放的具体信息

 * 我们存储的信息都是以key作为标识,所以key不能重复

 * 如果key信息重复,后面会把前面的给覆盖掉

public class HelloMap {

public static void main(String[]args) {

//创建对象

Map<String,Object>map = new HashMap<>();

//如何添加值

map.put("zhangsan", 1234567);

map.put("lisi","HelloMoto");

map.put("lisi","HelloKitty");

map.put("stu",new Student("zhangsan", 18));

//删除值

map.remove("lisi");

//取值

System.out.println(map.get("zhangsan"));

System.out.println(map.get("lisisi"));//键不存在时,输出null

//查看map的长度(即,存了几组值)

System.out.println(map.size());

//获取所有的key

Set keySet =map.keySet();

Collection collection =map.values();

//是否包含指定的key

System.out.println(map.containsKey("stu"));

//是否包含指定的值

System.out.println("包含值:" +map.containsValue(new Student("zhangsan", 18)));

//clear清空

map.clear();

System.out.println(map);

}

底层代码分析:

 *创建对象

 * //默认的初始容量16

 * static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  

 * //默认的使用的大小是总大小的75%

 * static final float DEFAULT_LOAD_FACTOR = 0.75f;

 * //map中数组可用的大小

 * int threshold;

 * //map中数组存放数据大小

 * int size;

 * //创建对象的时候默认创建一个空的entry数组,因为存储的内容都存放在                              entry当中

 * transient Entry[] table = (Entry[]) EMPTY_TABLE;

 * 存放数据

 * 第一次存放数据

 * 首先检查数组是不是默认的,如果是第一次需要创建一个新的

 * 新创建的数组是entry类型的,大小为16,可用为12

 * 计算keyhash值,相对是唯一的

 * 然后根据数组的大小计算当前key所应该处于的索引位置(hash值&数组大小)

 * 然后创建新的entry将数据存放至数组

 * 第一次之后加入数据(即,)

 * 首先计算key对应的hash值,算出对应的位置索引

 * 判断当前key有没有指定值,

 * 如果已经存在值

 * 就会把原来的值返回,并且新的value覆盖掉原来的值

 * 如果已经不存在值

 * 我们还需要判断当前数组容量是否足够

 * 扩容大小为原来的两倍,可用的大小也为原来的两倍,总大小的0.75

 * 最后将其存放至容器

 * 取出数据

 * 首先判断map是否为空,为空直接null

 * 不为空,计算当前keyhash值,然后计算索引值

 * 取出map的数组中指定位置的entry,然后进行比较

 * 比较当前对象,如果当前对象不equals,开始比较单向链表中的entry

 * 比较的时候先比较hash &&如果hash都不一样,对象肯定不一样,提高效率

 *

 * 为什么map数组的大小只允许使用75%

 * 假如数组用满,他并不是将数组的每个索引全部占用

 * 当我们用对象的hash值去&数组大小的时候,不可避免会产生相同的索引

 * 这样就会导致一个索引有可能存放两个不同key,这个时候使用单向链表解决

 * 首先数组索引指向新创建的entry,entry有一个next属性会指向原来的entry对象,形成一个单向链表。

 

 

 * 其实如果使用单向链表存储数据的时候,已经违背了map设计的思想

 * 所以我们最好重写每一个对象的hashcode方法

 * 当我们的map里面的数组进行扩容的时候,当扩容完毕,首先散列我们现有存储的对象,尽量把存在链表的地方给分开,提高查询效率

 *

 * Entry:记录

 * 我们map为了存放数据,所以专门创建的一个静态内部类

 * 类似于我们数组中的一个元素

 * entry里面有两个属性

 * key

 * value

 * 另外为了避免一些问题:不同hash算出相同index

 * next:

 * 另外为了查找更加的快捷,专门记录了keyhash

 * hash:比较的时候线比较hash

如何遍历Map

public static void main(String[]args) {

//如何遍历map

Map<String,String>map = new HashMap<>();

//存放数据

for (int i = 0; i < 20;i++) {

map.put("bjsxt" +i, "sxt" +i);

}

//获取map中所有的key,遍历所有的key

Set<String>set = map.keySet();

for (String key :set) {

System.out.println(map.get(key));

}

 

}

=======================================================================

Set

set接口中的元素是没有顺序的,而且是不能重复的。

 *创建过程

 * private static final Object PRESENT = new Object();

 * private transient HashMap<E,Object> map;

 * map = new HashMap();

 * set的底层就是一个map

 * 添加数据

 * map.put(e, PRESENT)

 * 其实就是向map中添加了一个Object对象

 * set中绝对不会有重复的值,会覆盖

 * 因为set就相当于mapkeykey是不会有重复的,所以set不会重复,相同的值只会保留一份

 *删除数据

 * map.remove(o)

//创建

Set<String>set = new HashSet<>();

//添加

for (int i = 0; i < 20;i++) {

set.add("bjsxt" +i);

}

//删除

set.remove("bjsxt1");

//只能迭代获取判断有无,不能直接获取

//set的遍历

//for (String string : set) {

//System.out.println(string);

//}

//迭代器

Iterator<String>iterator = set.iterator();

while (iterator.hasNext()) {

System.out.println(iterator.next());

}

================================================================================================

comparable

作用:排序

我们从list中存储数据时数据是根据哈希值以及数组长度计算的索引值,所以取出时是无序的。

list排序使用collections.sort()方法。

 该方法可以对字符串进行排序,但是当需要排序的内容不止一个字符串时,会报错

打开String源码,

public final class String

    implements java.io.Serializable, Comparable<String>, CharSequence {

发现String实现了Comparable接口。

因此想要按照一定顺序进行输出需要在具体类实现comparable接口,重写其方法compareTo,在方法中进行排序。代码:

@Override

public int compareTo(Studento) {

//首先获取年龄差

int flag =this.getAge() -o.getAge();

//按照年龄进行排序

if (flag == 0) {

//开始按照姓名排序

flag =this.getName().compareTo(o.getName());

if (flag == 0) {

//如果名字也一样 按照学号排序

flag =this.getSno().compareTo(o.getSno());

}

}

return flag;

}

尤其是当传入的是组合时。Comparable接口就显得尤为重要。

代码:

package com.bjsxt.ly;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

public class TestComparable {

public static void main(String[] args) {

}

private static void testCar() {

//创建一个容器对象

List<Car> list = new ArrayList<>();

//遍历并向其中添加数据

for (int i = 0; i < 10; i++) {

list.add(new Car("bjsxt" + (int) (Math.random() * 9), new Engine("sxt" + (int) (Math.random() * 9), (int) (Math.random() * 9)), new Interior("java" + (int) (Math.random() * 9)), new Tyre("ly" + (int) (Math.random() * 9))));

}

//排序

Collections.sort(list);

//对list进行排序

System.out.println(list);

}

private static void testStudent() {

//创建一个容器对象

List<Student> list = new ArrayList<>();

//遍历并向其中添加数据

for (int i = 0; i < 10; i++) {

list.add(new Student("sxt" + (int) (Math.random() * 9 + 1), "201601" + i, (int) (Math.random() * 11)));

}

//对list进行排序

Collections.sort(list);

System.out.println(list);

}

}

car:

package com.bjsxt.ly;

public class Carimplements Comparable<Car> {

private String type;

private Engineengine;

private Interiorinteriorl;

private Tyretyre;

public Car() {

}

public Car(String type, Engine engine, Interiorinteriorl, Tyretyre) {

super();

this.type =type;

this.engine =engine;

this.interiorl =interiorl;

this.tyre =tyre;

}

public String getType() {

return type;

}

public void setType(String type) {

this.type =type;

}

public Engine getEngine() {

return engine;

}

public void setEngine(Engineengine) {

this.engine =engine;

}

public Interior getInteriorl() {

return interiorl;

}

public void setInteriorl(Interiorinteriorl) {

this.interiorl =interiorl;

}

public Tyre getTyre() {

return tyre;

}

public void setTyre(Tyretyre) {

this.tyre =tyre;

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result =prime * result + ((engine ==null) ? 0 :engine.hashCode());

result =prime * result + ((interiorl ==null) ? 0 :interiorl.hashCode());

result =prime * result + ((type ==null) ? 0 :type.hashCode());

result =prime * result + ((tyre ==null) ? 0 :tyre.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this ==obj)

return true;

if (obj ==null)

return false;

if (getClass() !=obj.getClass())

return false;

Car other = (Car)obj;

if (engine ==null) {

if (other.engine !=null)

return false;

} else if (!engine.equals(other.engine))

return false;

if (interiorl ==null) {

if (other.interiorl !=null)

return false;

} else if (!interiorl.equals(other.interiorl))

return false;

if (type ==null) {

if (other.type !=null)

return false;

} else if (!type.equals(other.type))

return false;

if (tyre ==null) {

if (other.tyre !=null)

return false;

} else if (!tyre.equals(other.tyre))

return false;

return true;

}

@Override

public String toString() {

return "Car [type=" +type +", engine=" +engine + ", interiorl=" + interiorl + ", tyre=" +tyre + "]";

}

@Override

public int compareTo(Caro) {

//先比较车的牌子

int flag =this.getType().compareTo(o.getType());

if (flag == 0) {

//开始比较发动机

flag =this.getEngine().compareTo(o.getEngine());

if (flag == 0) {

//继续比较轮胎

flag =this.getTyre().compareTo(o.getTyre());

if (flag == 0) {

//继续比较内饰

flag =this.getInteriorl().compareTo(o.getInteriorl());

}

}

}

return flag;

}

 

}

算了,需要时看代码吧,太多了。

Testttttt/com.bjsxt.ly.comparable。

 

 

 

 

 

 

 

 

 

 

0 0