数组:Array
01.在内存中开辟一连串的空间
02..java有严格的数据类型限制,一个数组只能声明一个数据类型,存放同一种数据类型。
03.便于我们查询 因为有下标(索引)
04.增删的效率低,因为元素之后的数据都要改变
05.一旦数组初始化完成,数组的所占的内存空间将被固定,长度不可变,即使清空数组元素,内存空间依然存在,长度不变。
Arrays 数组的工具类
常用的方法
1.equals 比较两个数组是否相同
2.sort 排序 字母也可(字母排序似乎是按首字母来排序,然后再比较第二个字母,依次比较,数字排在字母前面)
3.toString 打印数组
链表:使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
1.链表失去了数组随机读取的优点
2.同时链表由于增加了结点的指针域,空间开销比较大。
链表共有三种;
1.单向链表:
单链表是链表中结构最简单的。一个单链表的节点(Node)分为两个部分,第一个部分(data)保存或者显示关于节点的信息,
另一个部分存储下一个节点的地址。最后一个节点存储地址的部分指向空值。
单向链表只可向一个方向遍历,一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。
而插入一个节点,对于单向链表,我们只提供在链表头插入,只需要将当前插入的节点设置为头节点,next指向原头节点即可。
删除一个节点,我们将该节点的上一个节点的next指向该节点的下一个节点。
用单向链表实现栈
栈的pop()方法和push()方法,对应于链表的在头部删除元素deleteHead()以及在头部增加元素addHead()。
2、双向链表
双向链表(double linked list): 是在单表单的每个结点中,再设置一个指向前驱结点的指针域。
因此,在双向链表中的结点都有两个指针域,一个指向前驱,一个指向后继。
3、循环链表
单向循环链表是单链表的另一种形式,其结构特点是链表中最后一个结点的指针不再是结束标记,而是指向整个链表的第一个结点,从而使单链表形成一个环。
在双向链表中,每个结点包括三个域,分别是element域、next域和prior域,其中element域为数据元素域,next域为指向后继结点的对象引用,prior域为指向前驱结点的对象引用。
集合:
Collection:集合类的根接口,产生了两个接口,就是Set和List。
Set中不能包含重复的元素。List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。
List : 存放的对象是有序的,同时也是可以重复的 public interface List<E> extends Collection<E>
ArrayList:
01.采用数组的形式来保存数据,默认10,每次扩充是1.5倍
02.查询的效率高
03.增删的效率低
LinkedList:
01.采用的是链表结构
02.查询的效率低
03.增删的效率高
Set: 存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中
public interface Set<E> extends Collection<E> 存储的是唯一无序的对象!
HashSet:
为什么Set存储的值是唯一的?
01.底层实现其实是HashMap
02.hashSet.add() 底层是hashMap.put()
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
03.把我们新增的元素作为了map的key进行存储了
HashMap的key怎么唯一的?
分析:
p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k)))
01.首先认识到一点:两个字符串的内容一致,hashCode绝对一致,
两个字符串的内容不一致,hashCode有可能一致
02.hash算法是效率最快的(比较字符串内容)
03.如果hash不一致,后续判断压根没必要执行
04.如果hash一致,还有可能内容不一致,所以继续判断
05.再比较内存地址,如果地址一致,证明内容一致,后续判断不执行
如果地址不一致,后续判断继续执行
06.实在没办法了,只能使用效率最低的equals
TreeSet:
TreeSet()是使用二叉树的原理对新add()的对象按照指定的顺序排序(升序、降序),每增加一个对象都会进行排序,将对象插入的二叉树指定的位置。
Map: 它和Collection接口没有关系,是相互独立的。 public interface Map<K,V>
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。
HashMap:HashMap是最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。因为键对象不可以重复,所以HashMap最多只允许一条记录的键为Null,允许多条记录的值为Null,是非同步的
TreeMap:TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,
当用Iterator遍历TreeMap时,得到的记录是排过序的。不允许key值为空,非同步的;
集合的工具类:
Collections:Java提供了一个操作Set、List和Map等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序、查询和修改等操作,
还提供了将集合对象设置为不可变、对集合对象实现同步控制等方法。
排序操作
static void reverse(List list); //反转指定List集合元素的顺序。
static void shuffle(List list); //对list集合元素进行随机排序(shuffle方法模拟了"洗牌动作")。
static void sort(List list); //根据元素的自然顺序对指定List集合的元素按升序进行排序。
static void sort(List list, Comparator c); //根据指定Comparator产生的顺序对List集合的元素进行排序。
static void swap(List list, int i, int j); //将指定list集合中i处元素和j处元素进行交换。
查找、替换操作
static int binarySearch(List list, Object key);
//使用二分搜索法搜索指定List集合,以获得指定对象在List集合中的索引。如果要该方法可以正常工作,必须保证List中的元素已经处于有序状态。
static Object max(Collection coll); //根据元素的自然排序,返回给定集合中的最大元素。
static Object max(Collection coll, Comparator comp); //根据指定Comparator产生的顺序,返回给定集合的最大元素。
static Object min(Collection coll); //根据元素的自然排序,返回给定集合中的最小元素。
static Object min(Collection coll, Comparator comp); //根据指定Comparator产生的顺序,返回给定集合的最小元素。
static void fill(List list, Object obj); //使用指定元素的obj替换指定List集合中所有元素。
static int frequency(Collection c, Object o); //返回指定元素中等于指定对象的元素数量。
static int indexOfSubList(List source, List target);
//返回List对象在母List对象中第一次出现的位置索引;如果母List中没有出现这样的子list则返回-1。
static int lastIndexOfSubList(List source, List target);
//返回List对象在母List对象中最后一次出现的位置索引;如果母List中没有出现这样的子list则返回-1。
static boolean replaceAll(List list, Object oldVal, Object newVal); //使用一个新值newVal替换List对象所有旧值oldVal。
同步控制
Collections类中提供了多个synchronizedXxx方法,该方法返回指定集合对象对应的同步对象,从而可以解决多线程并发访问集合时的线程安全问题。
设置不可变集合
Collections提供了如下三个方法来返回一个不可变的集合:
emptyXxx(); //返回一个空的、不可变的集合对象,此处的集合既可以是List,也可以是Set,还可以是Map。
singletonXxx(); //返回一个包含指定对象(只有一个或一项元素)的、不可变的集合对象,此处的集合既可以是List,也可以是Set,还可以是Map。
unmodifiableXxx(); //返回指定对象的不可变视图。此处的集合既可以是List,也可以是Set,还可以是Map。
上面三类方法的参数是原来集合对象,返回值是该集合的"只读"版本。通过上面Collections提供三类方法,可以生成"只读"的Collection或Map。
关于==和equals
==比较的是地址
equals比较的是值
eg:
String a="abc";
/**
* 01.在栈中开辟空间存储a
* 02.拿“abc”字符串去常量池中查询有没有,没有(第一次创建)
* 03.在常量池中开辟空间存储"abc"
* 04.栈中的a就指向了常量池中的"abc"地址
*/
String b="abc";
/**
* 01.在栈中开辟空间存储b
* 02.拿“abc”字符串去常量池中查询有没有,有
* 03.在常量池中不会开辟空间存储
* 04.栈中的b就指向了常量池中的"abc"原有地址
*/
String c=new String("abc");
/**
* 01.在栈中开辟空间存储c
* 02.拿“abc”字符串去常量池中查询有没有,有
* 有:直接去堆中开辟空间保存"abc"
* 没有:在常量池中开辟空间存储"abc",之后再去堆中开辟空间保存"abc"
* 03.栈中的c指向了堆的"abc"
*
*/
String d=new String("abc");
/**
* 01.在栈中开辟空间存储d
* 02.拿“abc”字符串去常量池中查询有没有,没有,不用管堆中有没有
* 03.栈中的c指向了堆的"abc"
*
*/
System.out.println(a==b); //true
System.out.println(a==c); //false
System.out.println(c==d); //false
如果是equals则都相等