集合框架

 

1.ArrayList

1.1与数组的区别

数组局限性:多了放不下,少了浪费

为了解决数组的局限性,引入容器类的概念。 最常见的容器类就是
ArrayList
capacity"会随着对象的增加,自动扩容,默认容量10,int newCapacity = (oldCapacity * 3)/2 + 1;
只需要不断往容器里增加即可,不用担心会出现数组的边界问题。

当数组的全部空间用尽,调用add时,数组列表将自动地创建一个更大的数组,并将所有对象从较小的数组中拷贝到较大的数组中。

优化:
     如果已经清楚或能够估计出数组可能存储的元素数量,就可以在填充数组之前调用ensureCapacity方法:
     staff.ensureCapacity(100);
   该方法调用将分配一个包含100个对象的内部数组。然后可以调用100次add,而不用重新分配空间。
   另外,还可以把初始容量传递给ArrayList构造器:
   ArrayList<Hero> hero =new ArrayList<>(100);  

1.2常用方法

add

增加 heros.add(3, specialHero);

 
contains

判断是否存在容器中。标准:是否是同一个对象,而不是name是否相同

 
get

获取指定位置的对象   越界会报错

 
indexOf

获取对象所处的位置。  标准:是否是同一个对象,而不是name是否相同

 
remove

删除   heros.remove(2);//根据下标删除,或者根据对象删除

 
set

替换  heros.set(5, new Hero("specialhero));

 
size

获取大小   

 
toArray

转换为数组 Hero hs[] = (Hero[])heros.toArray(new Hero[]{});//需要将类型告知toArray方法

 
addAll

把另一个容器所有对象都加进来 

 
clear清空集合 

1.3ArrayList和List

ArrayList实现了List接口,所以List接口的方法ArrayList都能用

ArrayList和List

常见的写法会把引用声明为接口List类型
注意:是java.util.List,而不是java.awt.List

public class TsetCollection {

public static void main(String[] args) {
        //接口引用指向子类对象(体现多态)
	List a1 = new ArrayList();
	a1.add(new Hero("盖伦"));
	System.out.println(a1.size());

	}
}

1.4泛型 Generic

  • 不指定泛型的容器,可以存放任何类型的元素
  • 指定了泛型的容器,只能存放指定类型的元素以及其子类
  • 泛型<Type>可以是类,抽象类,接口
public class TsetCollection {

public static void main(String[] args) {
	//对于不使用泛型的容器,可以往里面放英雄,也可以往里面放物品
	List a1 = new ArrayList();
	a1.add(new Hero("盖伦"));
	//本来用于存放英雄的容器,现在也可以存放物品了
	a1.add(new Item("血瓶"));
	//对象转型会出现问题
        
//容器里放的对象太多的时候,就记不清楚哪个位置放的是哪种类型的对象了
	

	//引入泛型Generic
    //声明容器的时候,就指定了这种容器,只能放Hero,放其他的就会出错
	List<Hero> a2 = new ArrayList<>();
	a2.add(new Hero("提莫"));
	//a2.add(new Item("宝剑"));  报错了
	//除此之外,还能存放Hero的子类
	//并且在取出数据的时候,不需要再进行转型了,因为里面肯定是放的Hero或者其子类
    Hero h = a2.get(0);
	}
}

1.5遍历

用for循环遍历

通过前面的学习,知道了可以用size()和get()分别得到大小,和获取指定位置的元素,结合for循环就可以遍历出ArrayList的内容

public static void main(String[] args) {
	//对于不使用泛型的容器,可以往里面放英雄,也可以往里面放物品
	List<Hero> heros = new ArrayList<>();
		//放5个Hero进去
	for(int i=0;i<5;i++) {
		heros.add(new Hero("hero"+i));
	}
	// 第一种遍历 for循环
    System.out.println("--------for 循环-------");
    for(int j=0;j<heros.size();j++) {
    	Hero h = heros.get(j);
    	System.out.println(h);
    }
	}

 迭代器遍历

public static void main(String[] args) {
	//对于不使用泛型的容器,可以往里面放英雄,也可以往里面放物品
	List<Hero> heros = new ArrayList<>();
		//放5个Hero进去
	for(int i=0;i<5;i++) {
		heros.add(new Hero("hero"+i));
	}
	//第二种遍历,使用迭代器
    System.out.println("--------for的迭代器-------");
    for(Iterator<Hero> it = heros.iterator();it.hasNext();){
    	Hero hero = it.next();
    	System.out.println(hero);
    }
    }

用增强型for循环

//第三种遍历,增强型for循环
    System.out.println("--------增强型for循环-------");
    for(Hero h:heros) {
    	System.out.println(h);
    }

使用增强型for循环可以非常方便的遍历ArrayList中的元素,这是很多开发人员的首选。

不过增强型for循环也有不足:

  • 无法用来进行ArrayList的初始化
  • 无法得知当前是第几个元素了,当需要只打印单数元素的时候,就做不到了。 必须再自定下标变量。

2.LinkedList 

序列分为:

  • 先进先出FIFO,在Java中又叫Queue 队列
  • 先进后出FILO,在Java中又叫Stack 栈

2.1 LinkedListList和List

ArrayList一样,LinkedList也实现了List接口,诸如add,remove,contains等等方法。

2.2双向链表 - Deque

除了实现了List接口外,LinkedList还实现了双向链表结构Deque,可以很方便的在头尾插入删除数据

双向链表 - Deque

public class TsetCollection {

public static void main(String[] args) {
	//对于不使用泛型的容器,可以往里面放英雄,也可以往里面放物品
	List<Hero> heros = new LinkedList<>();
	//LinkedList是一个双向链表结构的list
    LinkedList<Hero> ll =new LinkedList<Hero>();
     
    //所以可以很方便的在头部和尾部插入数据
    //在最后插入新的英雄
    ll.addLast(new Hero("hero1"));
    ll.addLast(new Hero("hero2"));
    ll.addLast(new Hero("hero3"));
    System.out.println(ll);
     
    //在最前面插入新的英雄
    ll.addFirst(new Hero("heroX"));
    System.out.println(ll);
     
    //查看最前面的英雄
    System.out.println(ll.getFirst());
    //查看最后面的英雄
    System.out.println(ll.getLast());
     
    //查看不会导致英雄被删除
    System.out.println(ll);
    //取出最前面的英雄
    System.out.println(ll.removeFirst());
     
    //取出最后面的英雄
    System.out.println(ll.removeLast());
     
    //取出会导致英雄被删除
    System.out.println(ll);
     
}
  
}

2.3 队列   Queue

LinkedList实现了Deque,进而又实现了Queue这个接口,Deque继承了Queue

Queue是先进先出队列 FIFO,常用方法:
offer 在最后添加元素
poll 取出第一个元素
peek 查看第一个元素

public class TestCollection {
  
    public static void main(String[] args) {
        //和ArrayList一样,LinkedList也实现了List接口
        List ll =new LinkedList<Hero>();
          
        //所不同的是LinkedList还实现了Deque,进而又实现了Queue这个接口
        //Queue代表FIFO 先进先出的队列
        Queue<Hero> q= new LinkedList<Hero>();
          
        //加在队列的最后面
        System.out.print("初始化队列:\t");
        q.offer(new Hero("Hero1"));
        q.offer(new Hero("Hero2"));
        q.offer(new Hero("Hero3"));
        q.offer(new Hero("Hero4"));
          
        System.out.println(q);
        System.out.print("把第一个元素取poll()出来:\t");
        //取出第一个Hero,FIFO 先进先出
        Hero h = q.poll();
        System.out.println(h);
        System.out.print("取出第一个元素之后的队列:\t");
        System.out.println(q);
          
        //把第一个拿出来看一看,但是不取出来
        h=q.peek();
        System.out.print("查看peek()第一个元素:\t");
        System.out.println(h);
        System.out.print("查看并不会导致第一个元素被取出来:\t");
        System.out.println(q);
          
    }
       
}

ArrayList和LinkedList还有Vector的区别

  • ArrayList 插入,删除数据慢
  • LinkedList, 插入,删除数据快
  • ArrayList是线程不安全的,多线程下使用Vector代替(有同步关键字),LinkedList也是线程不安全的。

ArrayList是顺序结构,所以定位很快,指哪找哪。 就像电影院位置一样,有了电影票,一下就找到位置了。
LinkedList 是链表结构,就像手里的一串佛珠,要找出第99个佛珠,必须得一个一个的数过去,所以定位慢

 

ArrayList和LinkedList的区别

 

3.HashMap 

3.1键值对

HashMap储存数据的方式是—— 键值对

public class TsetCollection {

public static void main(String[] args) {
	HashMap<String,String> cars = new HashMap<>();
	cars.put("b1", "宝马");// (key,value)
	cars.put("b2", "奔驰");
	cars.put("a", "奥迪");
	System.out.println(cars.get("b1"));//get(key)
	}
}

2.键不能重复,值可以重复  

对于HashMap而言,key是唯一的,不可以重复的。
所以,以相同的key 把不同的value插入到 Map中会导致旧元素被覆盖,只留下最后插入的元素。
不过,同一个对象可以作为值插入到map中,只要对应的key不一样

.

HashMap和Hashtable的区别

HashMap和Hashtable都实现了Map接口,都是键值对保存数据的方式

区别1:

  • HashMap可以存放 null(一个)
  • Hashtable不能存放null

区别2:

 

4.HashSet 

4.1Set中的元素,不能重复 

public class TsetCollection {

public static void main(String[] args) {
	HashSet<String> cars = new HashSet<>();
	HashSet<String> names = new HashSet<String>();
    
    names.add("gareen");
    //第二次插入同样的数据,是插不进去的,容器中只会保留一个
    names.add("gareen");
    System.out.println(names);
	}
}

4.2没有顺序 

Set中的元素,没有顺序。
严格的说,是没有按照元素的插入顺序排列

HashSet的具体顺序,既不是按照插入顺序,也不是按照hashcode的顺序。

以下是HashSet源代码中的部分注释

/**

* It makes no guarantees as to the iteration order of the set;

* in particular, it does not guarantee that the order will remain constant over time.

*/

即不保证Set的迭代顺序; 确切的说,在不同条件下,元素的顺序都有可能不一样


换句话说,同样是插入0-9到HashSet中, 在JVM的不同版本中,看到的顺序都是不一样的。 所以在开发的时候,不能依赖于某种臆测的顺序,这个顺序本身是不稳定的 。

4.3遍历

Set不提供get()来获取指定位置的元素,所以遍历需要用到迭代器,或者增强型for循环

public class TestCollection {
    public static void main(String[] args) {
        HashSet<Integer> numbers = new HashSet<Integer>();
         
        for (int i = 0; i < 20; i++) {
            numbers.add(i);
        }
         
        //Set不提供get方法来获取指定位置的元素
        //numbers.get(0)
         
        //遍历Set可以采用迭代器iterator
        for (Iterator<Integer> iterator = numbers.iterator(); iterator.hasNext();) {
            Integer i = (Integer) iterator.next();
            System.out.println(i);
        }
         
        //或者采用增强型for循环
        for (Integer i : numbers) {
            System.out.println(i);
        }
         
    }
}

 4.4HashMap和HashSet的关系

1、HashSet底层是采用HashMap实现的。HashSet 的实现比较简单,HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。
2、HashMap的key就是放进HashSet中对象,value是Object类型的。
3、当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该行的key就是向HashSet增加的那个对象,该行的value就是一个Object类型的常量 (private static final Object PRESENT = new Object();)

4.5HashSet LinkedHashSet TreeSet

HashSet: 无序

LinkedHashSet: 按照插入顺序
TreeSet: 从小到大排序

 

5.Collection  

Collection是 Set List Queue和 Deque的接口,是一个接口类,其继承了java迭代接口Iterable。
Queue: 先进先出队列
Deque: 双向链表

注:Collection和Map之间没有关系,Collection是放一个一个对象的,Map 是放键值对的
注:Deque 继承 Queue,间接得继承了 Collection

Collection

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值