赞
踩
1.集合与数组存储数据概述:
集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储。
2.数组存储的特点:
●一旦初始化以后,其长度就确定了。
●数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。 比如::String[] arr,int[] arr1,object[] arr2。
3.数组存储的弊端:
●—旦初始化以后,其长度就不可修改。
●数组中提供的方法非常限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
●获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
●数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
4.集合存储的优点:
解决数组存储数据方面的弊端。
单列集合框架结构
collection接口:单列集合,用来存储一个一个的对象
List接口:存储序的、可重复的数据。-->“动态”数组
ArrayList、LinkedList、Vector
Set接口:存储无序的、不可重复的数据-->高中讲的"集合”
HashSet、 LinkedHashSet、 TreeSet
1.contains(Object obj):判断当前集合中是否包含obj
2.containsAll(Conllection coll):判断coll中的所有元素是否都存在于当前集合中。
3.remove(Object obj):从当前集合中移除obj元素。
4.removeAll(Conllection coll):从当前集合中移除coll中的所有元素。
5.retainALL(Conllection coll):交集:获取当前集合和coll集合的交集,并返回给当前集合
/*** Collection coll = Arrays.asList(123,456,789);
coll.retainAll(coll); system.out.println(coll);
***/
6.equals(Object obj):想要返回true,需要当前集合和形参集合的元素都相同。
7.hashCode():返回当前对象的哈希值。
8.集合 ---> 数组:toArray()。
9.iterator():返回Iterator接口的实例,用于遍历集合元素。
集合对象每次调用Iterator()方法兜得到一个全新的迭代器对象,默认游标都在第一个元素之前。
- public class CollectionTest {
-
- @Test
- public void test1() {
- Collection coll = new ArrayList();
- coll.add(123);
- coll.add(456);
- coll.add(789);
- coll.add("A");
-
- Iterator iterator = coll.iterator();
-
- /** 方式一:
- System.out.println(iterator.next());
- System.out.println(iterator.next());
- System.out.println(iterator.next());
- System.out.println(iterator.next());
- //报异常:NoSuchElementException
- System.out.println(iterator.next());
- 方式二:不推荐
- for (int i = 0; i < coll.size(); i++) {
- System.out.println(iterator.next());
- }
- **/
-
- // 方式三:
- while (iterator.hasNext()){
- System.out.println(iterator.next());
- }
-
- }
-
-
-
-
-
- @Test
- public void test2() {
- Collection coll = new ArrayList();
- coll.add(123);
- coll.add(456);
- coll.add(789);
- coll.add("A");
-
- // 删除集合中A
- Iterator iterator = coll.iterator();
- while (iterator.hasNext()) {
- Object obj = iterator.next();
- if ("A".equals(obj)) {
- iterator.remove();
- }
- }
- // 遍历集合
- iterator = coll.iterator();
- while (iterator.hasNext()) {
- System.out.println(iterator.next());
- }
-
- }
-
- }

集合元素的遍历操作,使用迭代器Iterator接口
1.内部的方法: hasNext()和next()
2.集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
3.内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove()
测试中terator中的remove()
如果还未调用next()或在上一次调用next方法之后已经调用了remove方法/再调用remove都会报ILLegalstateException。
使用foreach循环遍历集合 ---Java5.0新特性
- public class ForeachTest {
- @Test
- public void test(){
- Collection coll = new ArrayList();
-
- coll.add(123);
- coll.add(456);
- coll.add(789);
- coll.add("A");
- // for(集合元素的类型 局部变量 :集合对象)
- for (Object obj : coll){
- System.out.println(obj);
- }
- }
- }
List接口概述
List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
JDK API中List接口的实现类常用的有: ArrayList、 LinkedList和IVector。
常用方法:
1. void add(int index, Object ele): 在index位置插入eLe元素
2. boolean addAll(int index, Collection eles): M从index位置开始将eles中的所有元素添加进来
3. object get(int index): 获取指定index位置的元素,如果不存在,返回-1。
4. int indexOf(Object obj): 返回obj在集合中首次出现的位置,如果不存在,返回-1。
5. int lastIndexOf(Object obj): 返回obj在当前集合中末次出现的位置
6. object remove(int index): 移除指定index位置的元素,并返回此元素
7. 0bject set(int index, object ele): 设置指定index位置的元素为ele
8. List subList(int fromIndex, int toIndex): 返回从fromIndex到toIndex位置的子集合
- public class ArrayListTest {
- @Test
- public void test1() {
- ArrayList list = new ArrayList();
- list.add(123);
- list.add(456);
- list.add("A");
- list.add(new Person("jiejie"));
-
- System.out.println(list);
-
- // void add(int index, Object ele): 在index位置插入eLe元素
- list.add(1, "B");
- System.out.println(list);
-
- // boolean addAll(int index, Collection eles): M从index位置开始将eles中的所有元素添加进来
- List list1 = Arrays.asList(1, 2, 3);
- list.addAll(list1);
-
- // list.add(list1); //按照整体
- System.out.println(list.size());
-
- // object get(int index): 获取指定index位置的元素
- System.out.println(list.get(0));
- }
-
- @Test
- public void test2() {
- ArrayList list = new ArrayList();
- list.add(123);
- list.add(456);
- list.add("A");
- list.add(new Person("jiejie"));
-
- // int indexOf(Object obj): 返回obj在集合中首次出现的位置,如果不存在,返回-1。
- int index = list.indexOf(456);
- System.out.println(index);
- //
- // int lastIndexOf(Object obj): 返回obj在当前集合中末次出现的位置,如果不存在,返回-1。
- System.out.println(list.lastIndexOf(456));
-
- // object remove(int index): 移除指定index位置的元素,并返回此元素
- Object obj = list.remove(0);
- System.out.println(obj);
-
- // 0bject set(int index, object ele): 设置指定index位置的元素为ele
- list.set(1,"C");
- System.out.println(list);
-
- // List subList(int fromIndex, int toIndex): 返回从fromIndex到toIndex位置的子集合
- List subList = list.subList(1,3);
- System.out.println(subList);
-
- }
- }

总结:常用方法
增:add(Object obj)
删:remove(int index) / remove(Object obj)
改:set(int index,Object ele)
查:get(int index)
插:add(int index,Object ele)
长度:size()
遍历:①Iterator迭代器遍历:
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next()); }
②增强for循环:
for (Object obj : list){
System.out.println(obj); }
③普通的循环
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i)); }
面试题::ArrayList、LinkedList、Vector三者的异同?
同:三个类都是实现了List接口,存储数据的特点相同:存储有序的、可重复的数据
不同:Collection接口: 单列集合,用来存储-一个一个的对象
List接口: 存储有序的、可重复的数据。 -->“动态”数组,替换原有的数组
ArrayList: 作为List接口的主要实现类;线程不安全的,效率高;底层使用0bject[] eLementData存储
LinkedList: 对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
Vector:作为List接口的由老实现类;线程安全的,效率低;底层使用0bject[] elementData存储
面试题:remove方法
- @Test
- public void test(){
- List list = new ArrayList();
- list.add(1);
- list.add(2);
- list.add(3);
- updateList(list);
- System.out.println(list);
- }
- private void updateList(List list){
- list.remove(2); // 删除索引2 返回1 2
- // list.remove(new Integer(2)); //删除数字2 返回1 3
- }
collection接口:单列集合,用来存储一个一个的对象
Set接口:存储无序的、不可重复的数据
HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值。
LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历。
TreeSet:可以按照添加对象的指定属性,进行排序。
1.Set接口中没有额外定义新的方法,使用的都是collection中声明过的方法。
2.要求:向Set中添加的数据,其所在的类一定要重写hashcode( )和equals()
要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码
重写两个方法的小技巧:对象中用作equals()方法比较的 Field,都应该用来计算hashCode
一、set:存储无序的、不可重复的数据
以Hashset为例说明:
1.无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值
2.不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个。
二、添加元素的过程:以Hashset为例:
我们向HashSet中添加元素a,首先调用元素α所在类的hashCode()方法,计算元素a的哈希值,
此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素:
如果此位置上没有其他元素,则元素α添加成功。--->情况1
如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
如果hash值不相同,则元素α添加成功。--->情况2
如果hash值相同,进而需要调用元素a所在类的equLas()方法:
equals()返回true,元素α添加失败
equals()返回false,则元素α添加成功。--->情况3
对于添加成功的情况2和情况3而言:元素a与已经存在指定索引位置上数据以链表的方式存储。
jdk 7 ︰元素α放到数组中,指向原来的元素。
jdk 8 ∶原来的元素在数组中,指向元素α总结:七上八下
HashSet底层:数组+链表的结构。
- @Test
- public void test1(){
- Set set = new HashSet();
- set.add(123);
- set.add(456);
- set.add("B");
- set.add("A");
- set.add(new Person("jiejie"));
-
- Iterator iterator = set.iterator();
- while (iterator.hasNext()){
- System.out.println(iterator.next());
- }
LinkedHashSet的使用
LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个数据和后一个数据。
优点:对于频繁的遍历操作,LinkedHashSet效率高于Hashset
- @Test
- public void test2(){
- Set set = new LinkedHashSet();
- set.add(123);
- set.add(456);
- set.add("B");
- set.add("A");
- set.add(new Person("jiejie"));
-
- Iterator iterator = set.iterator();
- while (iterator.hasNext()){
- System.out.println(iterator.next());
- }
- }
TreeSet
1.向Treeset中添加的数据,要求是相同类的对象。
2.两种排序方式:自然排序(实现Comparable接和定制排序
3.自然排序中,比较两个对象是否相同的标准为: compareTo()返回e.不再是equals().
- @Test
- public void test1() {
- TreeSet set = new TreeSet();
- //失败:不能添加不同类的对象
- // set.add(123);
- // set.add(456);
- // set.add("B");
- // set.add("A");
- // set.add(new Person("jiejie"));
-
- set.add(123);
- set.add(456);
- set.add(-123);
-
-
- Iterator iterator = set.iterator();
- while (iterator.hasNext()) {
- System.out.println(iterator.next());
- }
- }

- // 按照名字从小到大排序 -this的话则为从大到小
- @Override
- public int compareTo(Object o) {
- if (o instanceof Person){
- Person person = (Person) o;
- return this.name.compareTo(person.name);
- }else {
- throw new RuntimeException("输入的类型不匹配");
- }
- }
-
-
- //自然排序
- @Test
- public void test2() {
- TreeSet set = new TreeSet();
-
- set.add(new Person("flandre"));
- set.add(new Person("jiejie"));
- set.add(new Person("scout"));
- set.add(new Person("viper"));
- set.add(new Person("meiko"));
-
- Iterator iterator = set.iterator();
- while (iterator.hasNext()) {
- System.out.println(iterator.next());
- }
- }

- //定制排序
- @Test
- public void test3() {
- Comparator com = new Comparator() {
- //按照年龄从小到大排序
- @Override
- public int compare(Object o1, Object o2) {
- if (o1 instanceof Person && o2 instanceof Person){
- Person p1 = (Person) o1;
- Person p2 = (Person) o2;
- return Integer.compare(p1.getAge(),p2.getAge());
- }else {
- throw new RuntimeException("输入的数据类型不匹配");
- }
- }
- };
-
- TreeSet set = new TreeSet(com);
- set.add(new Person("flandre",23));
- set.add(new Person("jiejie",20));
- set.add(new Person("scout",23));
- set.add(new Person("viper",21));
- set.add(new Person("meiko",23));
-
- Iterator iterator = set.iterator();
- while (iterator.hasNext()) {
- System.out.println(iterator.next());
- }
- }

关于Set的面试题:
- //面试题1
- @Test
- public void test4(){
- HashSet set = new HashSet();
- Person p1 = new Person(1001, "AA");
- Person p2 = new Person(1002, "BB");
-
- set.add(p1);
- set.add(p2);
- p1.name = "CC";
- set.remove(p1);//在set中删除 先找哈希值 没有就不删
- System.out.println(set);
- set.add(new Person(1001,"CC"));
- System.out.println(set);
- set.add(new Person(1001,"AA"));
- System.out.println(set);
- //[Person{id='1002', name='BB'}, Person{id='1001', name='CC'}]
- //[Person{id='1002', name='BB'}, Person{id='1001', name='CC'}, Person{id='1001', name='CC'}]
- //[Person{id='1002', name='BB'}, Person{id='1001', name='CC'}, Person{id='1001', name='CC'}, Person{id='1001', name='AA'}]
- }

一:Map: 双列数据,存储key-value对的数据 。 ---类似于高中的函数: y = f(x)
HashMap:作为Map的主要实现类;线程不安全的,效率高;存储nulL的key和value
LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
原因:在原有的HashMap底层结构基础上,添加了- -对指针,指向前一个和后 一个元 素。对于频繁的遍历操作,此类执行效率高于HashMap。
TreMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
底层使用红黑树
Hashtable:作为古老的实现类;线程安全的,效率低;不能存储nulL的key和value
Properties:常用来处理配置文件。key和value都是String类型
二、Map结构的理解:
Map中的key:无序的、不可重复的,使用Set 存储所有的key ---> key所在的类要重写equals()和hashCode() ( 以HashMap为例)
Map中的value:无序的、可重复的,使用Collection存储所有 的value --->value所在的类要 重写equaLs()
一个键值对::key-value构成了一个Entry对象。
Map中的entry:无序的、不可重复的,使用set存储所有的entry
三、HashMap的底层实现原理?以jdk7为例说明:面试题
HashMap map = new HashMap( ) :
在实例化以后,底层创建了长度是16的一维数组Entry[] table。
可能已经执行过多itput
map.put(key1, vaLue1):
首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
如果此位置上的数据为空,此时的key1-value1添加成功。---- 情况1
如果此位置上的数据不为空,(意味着此位置上存在一个或多 个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1 添加成功。----情况2
如果key1的哈希值和已经存在的某一个数 据(key2-vaLue2)的哈希值相同,继续比较:调用key1 所在类的equaLs(key2)
如果equals().返回false:此时key1-value1添加成功。---- 情况3
如果equals()返回true:使用value1替换value2。
补充:关于情况2和情况3:此时key1-value1 和原来的数据以链表的方式存储。
在不断的添加过程中,会涉及到扩容问题,默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。
jdk8相较于jdk7在底层实现方面的不同:
1. new HashMap():底层没有创建-一个长度为16的数组
2. jdk 8底层的数组是::Node[],而非Entry[]
3. 首次调用put()方法时,底层创建长度为16的数组
4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树。
四、 Map 中定义的方法:
添加、删除、修改操作:
Object put(Object key, object value):将指定key-vaLue 添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
object remove(object key):移除指定key的key-value对, 并返回value
void clear():清空当前map中的所有数据
元素查询的操作:
0bject get(0bject key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(0bject vaLue):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(object obj):判断当前map和参数对象obj是否相等
元视图操作的方法:
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合
Properties:常用来处理配置文件。key 私value都是String类型
-
- public class mapTest {
- @Test
- public void test1(){
- HashMap map = new HashMap();
- map.put("AA",123);
- map.put(44,123);
- map.put("BB",456);
-
- //遍历所有的key集:keySet()
- Set set = map.keySet();
- Iterator iterator = set.iterator();
- while (iterator.hasNext()){
- System.out.println(iterator.next());
- }
-
- //遍历所有的value集:values()
- Collection values = map.values();
- for (Object obj : values){
- System.out.println(obj);
- }
-
- //遍历所有的key-value:entrySet()
- //方式一
- Set entrySet = map.entrySet();
- Iterator iterator1 = entrySet.iterator();
- while (iterator1.hasNext()){
- Object obj = iterator1.next();
- //entrySet集合中的元素都是entry
- Map.Entry entry = (Map.Entry) obj;
- System.out.println(entry.getKey()+"--->"+entry.getValue());
- }
-
- //方式二
- Set keySet = map.keySet();
- Iterator iterator2 = keySet.iterator();
- while (iterator2.hasNext()){
- Object key = iterator2.next();
- Object value = map.get(key);
- System.out.println(key+"-----"+value);
- }
- }
- }

- //自然排序
- @Test
- public void test1() {
- TreeMap map = new TreeMap();
- Person p1 = new Person("flandre",23);
- Person p2 = new Person("jiejie",20);
- Person p3 = new Person("scout",23);
- Person p4 = new Person("viper",21);
- Person p5 = new Person("meiko",23);
- map.put(p1,94);
- map.put(p2,99);
- map.put(p3,95);
- map.put(p4,96);
- map.put(p5,95);
-
- Set entrySet = map.entrySet();
- Iterator iterator1 = entrySet.iterator();
- while (iterator1.hasNext()){
- Object obj = iterator1.next();
- Map.Entry entry = (Map.Entry) obj;
- System.out.println(entry.getKey()+"--->"+entry.getValue());
- }
-
- }
- //定制排序
- @Test
- public void test2(){
- TreeMap map = new TreeMap(new Comparator() {
- @Override
- public int compare(Object o1, Object o2) {
- if (o1 instanceof Person && o2 instanceof Person){
- Person p1 = (Person)o1;
- Person p2 = (Person)o2;
- return Integer.compare(p1.getAge(),p2.getAge());
- }
- throw new RuntimeException("输入的类型不匹配");
- }
- });
-
-
- Person p1 = new Person("flandre",23);
- Person p2 = new Person("jiejie",20);
- Person p3 = new Person("scout",23);
- Person p4 = new Person("viper",21);
- Person p5 = new Person("meiko",23);
- map.put(p1,94);
- map.put(p2,99);
- map.put(p3,95);
- map.put(p4,96);
- map.put(p5,95);
-
- Set entrySet = map.entrySet();
- Iterator iterator1 = entrySet.iterator();
- while (iterator1.hasNext()){
- Object obj = iterator1.next();
- Map.Entry entry = (Map.Entry) obj;
- System.out.println(entry.getKey()+"--->"+entry.getValue());
- }
-
- }
-
-
- // 按照名字从大到小排序,年龄从小到大
- @Override
- public int compareTo(Object o) {
- if (o instanceof Person){
- Person person = (Person)o;
- int compare = -this.name.compareTo(person.name);
- if (compare != 0){
- return compare;
- }else {
- return Integer.compare(this.age,person.age);
- }
- }else {
- throw new RuntimeException("输入的类型不匹配");
- }

总结:常用方法:
添加:put(0bject key, object vaLue)
删除:remove(0bject key)
修改:put(object key, Object value )
查询:get(object key)
长度:size()
遍历:keySet() / values() / entrySet()
面试题:Collection 和 Collections 的区别?
collection:存储单列数据的一个集合接口,常见的子接口为list、set
collections:一个操作collection的工具类
Collection的常用方法:
排序操作:(均为static方法 )
●reverse(List):反转List 中元素的顺序
●shuffle(List):对List集合元素进行随机排序
●sort(List):根据元素的自然顺序对指定List集合元素按升序排序
●sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
●swap(List,int, int):将指定list集合中的i处元素和j处元素进行交换
查找、替换
●Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
●Object max(Collection,Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
●Object min(Collection)
●Object min(Collection,Comparator)
●int frequency(CollectionI Object):返回指定集合中指定元素的出现次数
●void copy(List dest,List src):将src中 的内容复制到dest中
●boolean replaceAll(List list,Object oldVal, Object newVal):使用新值替换List对象的所有旧值
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。