java 集合框架学习_java基础学习:集合(容器)

集合

1. 为什么要使用集合框架?

传统的容器(数组)在进行增、删等破坏性操作时,需要移动元素,可能导致性能问题;同时添加、删除等算法和具体业务耦合在一起,增加了程序开发的复杂度。

Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中。

2. Collection

Collection是java集合框架(collection-frame)中的顶层接口。

Collection接口是一个容器,容器中只能存储引用数据类型,建议存同一类型的引用类型,方便后续遍历等操作。

容器中的元素可以是有序的、可重复的,称为List接口。

也可能是无序的、不可重复(唯一)的,称为Set接口。

2.1 集合常用方法

public static void main(String[] args) {

/*** 增:add/addAll* 删:clear/remove/removeAll/retainAll* 改:* 查:contains/containsAll/isEmpty/size*/

Collection c1 = new ArrayList();

// 追加c1.add("apple"); // Object object = new String("apple");// c1.add(1); // Object object = new Integer(1);c1.add("banana");

System.out.println(c1);//[apple, banana]

// 追加一个集合Collection c2 = new ArrayList();

c2.add("java");

c2.add("c++");

c1.addAll(c2);

System.out.println(c1);//[apple, banana, java, c++]

// clear//c1.clear();

// c1.remove("apple");// c1.removeAll(c2);//c1.retainAll(c2);//System.out.println(c1);//返回布尔类型,contains是否包含这个值System.out.println(c1.contains("apple"));//truec2.add("js");

System.out.println(c1.containsAll(c2));//false// c1.clear();System.out.println(c1.isEmpty());//false// 返回集合元素的个数System.out.println(c1.size());//4

System.out.println(c1.equals(c2));//false

}

2.2 集合的遍历

Iterable 可遍历的接口,集合接口继承于它,集合支持快速遍历。

// 快速遍历// for-each// Object 表示元素类型// item表示迭代变量// c1表示集合for (Object item : c1) {

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

}

快速遍历的本质:Collection继承Iterable接口,表示集合支持快速遍历。Iterable接口定义了一个方法iterator()用于获取集合的迭代器,是一个Iterator接口类型,iterator()内部返回一个实现类实现Iterator接口。这个实现类一定具有hasNext和next方法用于判断是否有下一个元素和获取下一个元素。快速遍历就是基于迭代器工作的。

public static void main(String[] args) {

Collection c1 = new ArrayList();

c1.add("apple");

c1.add("banana");

c1.add("coco");

// 快速遍历// for-each// Object 表示元素类型// item表示迭代变量// c1表示集合for (Object item : c1) {

System.out.print(item.toString()+"");//apple banana coco}

// 迭代器遍历(国内)Iterator it = c1.iterator();

while(it.hasNext()) {

Object item = it.next();

System.out.print(item.toString()+"");//apple banana coco}

// 国外for(Iterator it2=c1.iterator();it2.hasNext();) {

Object item = it2.next();

System.out.println(item.toString()+"");//apple banana coco}

}

3. List接口

List 接口中的元素时有序的、可重复的。List接口中的元素通过索引(index)来确定元素的顺序。

有序的 collection(也称为序列)。可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

3.1 list常用方法

public static void main(String[] args) {

/*** 增:add/addAll/add(index,el)/addAll(index,collection)* 删:clear/remove/removeAll/remove(index)* 改:set(index,el)* 查:get(index)/indexOf/lastIndexOf()* 其他:contains/containsAll/isEmpty/size*/

List list1 = new ArrayList();

// 添加元素list1.add("apple");

list1.add("banana");

// 在指定位置添加元素list1.add(0, "coco");

System.out.println(list1);//[coco, apple, banana]

List list2 = new ArrayList();

list2.add("java");

list2.add("c++");

list1.addAll(1, list2);

System.out.println(list1);//[coco, java, c++, apple, banana]

// 删除list1.remove(0);

System.out.println(list1);//[java, c++, apple, banana]

// 修改list1.set(0, "javax");

System.out.println(list1);//[javax, c++, apple, banana]

// 查System.out.println(list1.get(0));//javaxlist1.add("apple");

list1.add("apple");

System.out.println(list1);//[javax, c++, apple, banana, apple, apple] //indexOf:查找字符或者子串第一次出现的地方System.out.println(list1.indexOf("apple"));//2System.out.println(list1.lastIndexOf("apple"));//5}

3.2 List接口遍历

ListIterator 继承于Iterator,在Iterator的基础上提供了以正向遍历集合,也可以以逆序遍历集合。

hasNext/next 以正向遍历。

hasPrevious/previous 以逆序遍历。

public static void main(String[] args) {

List list1 = new ArrayList();

list1.add("apple");

list1.add("banana");

list1.add("coco");

// 【1】快速遍历System.out.println("--for each--");

for (Object item : list1) {

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

}

// 【2】普通forSystem.out.println("--for--");

for(int i=0;i

System.out.println(list1.get(i));

}

// 【3】集合迭代器System.out.println("--iterator--");

Iterator it = list1.iterator();

while(it.hasNext()) {

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

}

System.out.println("--list iterator--");

// 正向遍历ListIterator it2 = list1.listIterator();

while(it2.hasNext()) {

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

}

// 逆序遍历while(it2.hasPrevious()) {

System.out.println(it2.previous());

}

System.out.println("--list iterator with index--");

ListIterator it3 = list1.listIterator(1);

while(it3.hasNext()) {

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

}

}

4. 数据结构

数据结构就是数据在内存中存储结构。根据存储的方式不同,分为线性表、二叉树、图、栈、队列等

4.1 线性表

线性表数据按照一定的逻辑顺序存储在内存中。线性表是有序的。线性表根据内存的物理结构分为两种:数组和链表

数组是一种逻辑上有序的线性表,物理上也连续。

链表是一种逻辑上有序的线性表,但物理上不连续。

数组和链表的区别

相同点:在逻辑上是有序的。

不同点:1.数组在查询时效率高,在添加、删除元素时效率低(涉及移动元素) 2.链表在查询时效率低(每次从头开始,不能跳跃访问),在添加、删除元素时效率高(不涉及移动元素)

4.2 栈

特性:先进后出,后进先出(就像子弹夹中的子弹)

4.3 队列

特性:先进先出

5. ArrayList/Vector

ArrayList 是List接口的实现类,底层数据结构是数组,实现大小可变的数组。

ArrayList 线程不安全,jdk1.2开始。

ArrayList 底层数据结构是数组,默认数组大小是10,如果添加的元素个数超过默认容量,ArrayList会自动拓容,拓容原则:newCapacity = oldCapacity + oldCapacity / 2;

如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。

ArrayList作为List接口的实现类,常用方法和遍历方法参考List接口。

Vector 是List接口的实现类,底层数据结构也是数组,也是大小可变的数组。

Vector是线程安全的,jdk1.0开始。

Vector底层数据结构是数组,默认数组大小是10,如果添加的元素个数超过默认容量,Vector会自动拓容,拓容原则:newCapacity = oldCapacity +capacityIncrement(增长因子);如果未来确定序列的元素不在增加,通过调用trimToSize()调制容量至合适的空间。

注意:Vector 在实现List接口的同时,添加了自身特有的方法xxxElement,未来使用时为了程序的可拓展性,一定要按照接口来操作Vector。

6. LinkedList

LinkedList是List接口的实现类,底层数据结构是链表。

LinekList常用方法和遍历方法参照List接口。

LinkedList 线程不安全。

除了实现List接口, 还实现栈接口。

push入栈操作 / pop出栈操作

public class Test01 {

public static void main(String[] args) {

LinkedList list = new LinkedList();

list.push("apple");

list.push("banana");

list.push("coco");

System.out.println(list.pop());//cocoSystem.out.println(list.pop());//bananaSystem.out.println(list.pop());//apple

// java.util.NoSuchElementExceptionSystem.out.println(list.pop());

}

}

队列(Queue)接口

add/remove/element() 可能会出现NoSuchElementException异常

public static void main(String[] args) {

LinkedList queue = new LinkedList();

// 入队/*** 队列头 队列尾*

queue.add("apple");

queue.add("banana");

queue.add("coco");

System.out.println(queue);//[apple, banana, coco]

// 出队System.out.println(queue.remove());//appleSystem.out.println(queue.remove());//bananaSystem.out.println(queue.remove());//cocoSystem.out.println(queue);//[]

// java.util.NoSuchElementExceptionSystem.out.println(queue.remove());

// 获取表头元素System.out.println(queue.element());

}

offer/poll/peek 可能会返回特殊值(null)

public static void main(String[] args) {

LinkedList queue = new LinkedList();

// 入队/*** 队列头 队列尾*

queue.offer("apple");

queue.offer("banana");

queue.offer("coco");

// 出队列System.out.println(queue.poll());//appleSystem.out.println(queue.poll());//bananaSystem.out.println(queue.poll());//cocoSystem.out.println(queue);//[]

System.out.println(queue.poll());//null

// 获取表头元素System.out.println(queue.peek());//null

}

双向队列(Deque)接口

/*** 以双向队列形式操作LinkedList*/

public class Test04 {

public static void main(String[] args) {

LinkedList queue = new LinkedList();

// 入队/*** ----->*/

queue.addFirst("apple");

queue.addFirst("banana");

queue.addFirst("coco");

System.out.println(queue);//[coco, banana, apple]

System.out.println(queue.removeLast());//appleSystem.out.println(queue.removeFirst());//cocoSystem.out.println(queue.removeFirst());//bananaSystem.out.println(queue);//[]

// 获取头元素System.out.println(queue.getFirst());

}

}

7. Iterator和ListIterator

Iterator在迭代过程中不允许向集合中添加元素。

public static void main(String[] args) {

ArrayList list = new ArrayList();

list.add("apple");

list.add("banana");

list.add("coco");

Iterator it = list.iterator();

while(it.hasNext()) {

String item = (String) it.next();

if(item.equals("banana")) {

list.add("test");

}

}

System.out.println(list);//ConcurrentModificationException}

当通过Iterator集合迭代器遍历集合过程中,不能再向集合汇总添加元素,否则出现ConcurrentModificationException 并发修改异常。

ListIterator允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置

public class Test01 {

public static void main(String[] args) {

ArrayList list = new ArrayList();

list.add("apple");

list.add("banana");

list.add("coco");

ListIterator it = list.listIterator();

while(it.hasNext()) {

String item = (String) it.next();

if(item.equals("banana")) {

it.add("test");

}

}

System.out.println(list);//[apple, banana, test, coco]}

}

8. 泛型(generic)

8.1泛型的概念

泛型允许开发者在强类型程序设计语言(java)编写代码时定义一些可变部分,这些部分在使用前必须作出指明。

泛型就是将类型参数化

ArrayList list表示声明了一个列表list,列表的元素是E类型

ArrayList list = new ArrayList();

声明了一个列表list,列表的元素只能是String类型。

8.2 泛型的擦除

泛型在运行时已经被擦除了。

public static void main(String[] args) {

ArrayList list = new ArrayList();

list.add("apple");

System.out.println(list instanceof ArrayList);

System.out.println(list instanceof ArrayList);

}

Cannot perform instanceof check against parameterized type ArrayList. Use the form ArrayList> instead since further generic type information will be erased at runtime(无法对参数化类型ArrayList执行instanceof检查。使用ArrayList>,因为更多的泛型类型信息将在运行时被删除)

8.3 泛型的应用

8.3.1 泛型类

当一个类中属性的数据类型不确定时,具体是什么类型由使用者来确定时,使用泛型。泛型类的形式

public class 类名 {

}

定义一个泛型类

public class FanClass {

private T t;

public T getT() {

return t;

}

public void setT(T t) {

this.t = t;

}

public FanClass(T t) {

super();

this.t = t;

}

public FanClass() {

super();

}

}

public class Test01 {

public static void main(String[] args) {

FanClass fan = new FanClass();

fan.setT("apple");

FanClass fan2 = new FanClass();

fan2.setT(1);

}

}

8.3.2 泛型方法

当一个方法的参数类型不确定时,具体是什么类型由使用者来确定,可以考虑使用泛型方法。形式。

public void xxx(T a) {

System.out.println(a);

}

public class Student {

/*public void showInfo(int a) {System.out.println(a);}public void showInfo(float a) {System.out.println(a);}public void showInfo(String a) {System.out.println(a);}*/

public void showInfo(T a) {

System.out.println(a);

}

}

public static void main(String[] args) {

Student stu = new Student();

stu.showInfo(1);

stu.showInfo("apple");

stu.showInfo(1.0f);

}

泛型方法在调用时确定(指明)类型。

泛型方法在一定程度上优化了方法重载。

泛型方法可以定义多个泛型类型。

// 可以定义多个泛型的类型public void showInfo(A a,B b) {

System.out.println(a);

System.out.println(b);

}

多个泛型类型进一步优化了方法重载。

多个同类型的泛型

// 多个同类型的泛型/*public void print(A a) {System.out.println(a);}public void print(A a,A b) {System.out.println(a);System.out.println(b);}*/

public void print(A...a) {

System.out.println(a);

}

A… a 表示方法可以接受多个参数。当调用方法传递多个参数时,多个参数被放到a数组中,a是什么类型的数组由开发者调用处传参决定。

stu.print(1);

stu.print(1,2);

stu.print("apple");

stu.print("apple","banana");

print(A...a) 方法称为可变参数的泛型形式。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值