java集合的缺点_集合的总结与常见问题解析

1、如何定义Collection?

Collection是一个集合体系的顶层接口,此接口中的方法都是:public abstract。

可以进行增删改查的操作:

增加: -->> boolean add(Object o) 一次添加一个元素,元素可以是Object 的子类,返回true

boolean addAll(Collection c) 一次添加一批元素,参数是Collection类型的

删除: -->> void clear() 清空集合

boolean remove(Object o) 一次删除一个元素,成功删除,返回true

boolean removeAll(Collection c) 一次删除一批,成功,返回true

查找: -->> boolean contains(Obejct o) 判断集合中是否包含指定元素

boolean containsAll(Collection c) 是否包含一批

boolean isEmpty() 判断集合是否为空

int size() 获取集合中的个数

修改: -->> clear() 清空集合中的所有元素

获取: -->> int size() 返回集合容器的大小

集合转换为数组:

Object[] toArray(); 该方法将集合转为数组,集合中的每一个元素,作为了数组一个的元素

【注意:集合中存储的是对象的引用,而不是对象本身】

【注意:接口与接口之间属于:继承关系】

2、录入用户在控制台输入的信息,可以使用Scanner类

Scanner sc = new Scanner();

3、List接口: ---->> public interface List extends Collection

List是一个继承了Collection接口的接口,具备了比Collection多的功能。

特点: ---->> 有序、有角标、可重复。

此接口的用户可以对List接口中每个元素的插入位置进行精确地控制。(通过角标获取集合中的元素)

增:

void add(int index,Object element) 指定元素添加的角标,增加一个元素

boolean addAll(int index,Collection c) 指定位置,增加一批

删:

Element remove(int index) 删除指定位置的元素,并且返回该元素

改:

Element set(int index,Object element) 替换指定位置的元素,需要确定该元素的位置和新元素,返回就元素。

ListsubList(int fromIndex,int toIndex) 截取子结合,返回一个List,包含头,不包含尾。

查:

Object get(int index) 获取List结合指定位置的元素

int indexOf(Object o) 返回此列表中第一次出现的指定元素的索引

int lastIndexOf(Object o) 倒序查找指定元素的位置

【注意角标越界:IndexOutOfBoundException // 找不到返回:-1】

【Object set = new list.get(list.size()-1);】

【List集合特有的增删改查方法都跟角标有关系!!!!】

【问:如何取出List集合中的元素?】

通过for循环,并使用size()和set()方法可取出List集合中的每一个元素。

4、ArrayList -->> 是一个List接口的实现类

具备List集合的特点:有序、有角标、可重复。

该类内部,维护了一个数组, 数组的元素是Object 类.

在ArrayList 类的构造函数中初始化的该数组, 如果没有显示的指定数组的长度,【默认长度是10】

也就是说: 使用无参数构造,new ArraList(), 自动创建的数组长度是60%.

ArrayList 在添加元素时,都会检测数组是否已满,如果满了,自动扩容(创建一个新数组),

【新数组长度的是老数组的1.6倍】

并且将老数组中的元素拷贝到了新数组,使用新数组继续增加元素.

5、ArrayList使用什么实现的?其优缺点是什么?

ArrayList是使用数组实现的。

优点:内存地址连续,查找快;

缺点:增加和删除元素,需要设计数组的扩容或者拷贝,效率很低。

---->> 总结: 数组实现,查找快,增删慢。

ArrayList中的方法:

boolean contains(Object o) 判断集合是否包含指定的元素,涉及了元素的比较(对象的比较)

内部使用了元素的equals()方法。

String类 重写了equals()方法

6、LinkedList ---->> List接口的实现类,具备:有序、有角标、元素可重复的特点。【和ArrayList类似】

LinkedList是一个双向链表,该集合提供了方便操作集合头和集合尾的方法。

【如果集合中没有元素可以获取或者删除,则抛:NoSuchElementException】

LinkedList特有的方法:

增加:

void addFirst(Element e)

void addLast(Element e)

删除:

Object getFirst()

Object getLast()

查找:

Object removeFirst() 移除并返回此列表的第一个元素

Object removeLast() 移除并返回此列表的最后一个元素

数据结构:

堆栈:

void push(Element e) 将元素推入此列表所表示的堆栈

Element pop() 从此列表所表示的堆栈处弹出一个元素

【压栈和弹栈:先进后出,后进先出】

队列:

boolean offer(Element e) 将指定元素添加到此列表的末尾(最后一个元素)

Element poll() 获取并移除此列表的头(第一个元素)

Element peek() 获取但不移除列表的头(第一个元素)

【队列的数据结构:先进先出】

返回逆序的迭代器对象:

descendingIterator() 返回逆序的迭代器对象

7、LinkedList的实现原理是什么?其优缺点?

LinkedList的实现原理是:链表实现,其内存地址是不连续的。

优点:相对于数组,增加元素快;

缺点;由于内存地址不连续,查找性能低。

8、集合与数组有什么区别?

相同点:数组和集合都是容器

数组和集合中存放的都是【对象的引用】而非对象本身

不同点:数组存储【基本数据类型】,是单一的。而且一旦声明好长度后,长度不可变;

集合【只能】储存【对象】,但是可以是任意类型的对象,其长度可变。

【集合的分类】

----|Iterable:接口

Iterator iterator()

----|Collection:单列集合

----|List: 有序存储顺序,可重复

----|ArrayList: 数组实现,查找快、增删慢

由于是数组实现,在增和删的时候会牵扯到数组增容,以及拷贝元素,所以慢;

数组是可以直接按索引查找的,所以查找时比较快。

----|LinkedList: 链表实现,增删快、查找慢

由于链表实现,增加时只要让前一个元素记住自己就可以了,删除时让前一个元

素记住后一个元素,后一个元素记住前一个元素,这样的增删效率高;

但查询时需要一个一个的遍历,所以效率比较低。

----|Vector: 多线程安全、效率略低 【ArrayList单线程效率高,但是多线程要使用Vector】

----|set: 无序存储,不可重复

----|HashSet 线程不安全,存取速度快

底层是以hash表实现的

----|TreeSet 红-黑树的数据结构,默认对元素进行自然排序(String)

【TreeSet自身具备排序功能】

----|Comparable

----|compareTo(Object o) 元素自身具备比较性

----|Comparator

----|compare(Object o1,Object o2) 给容器传入比较器

如果在比较的时候两个对象返回值是【0】,那么这两个元素【重复】

【当Comparable和Comparator比较方式同时存在时,以Comparator比较方式为主】

----|LinkedHashSet 会保存插入的顺序

----|Map: 将键映射到值的对象。一个映射不能包含重复的键,每个键最多只能映射一个值。

interface Map

----|TreeMap 底层是二叉树数据结构,可以对map集合中的键进行排序

需要使用Comparable或者Comparator进行比较排序。

【return 0 判断键的唯一性】

----|HashTable 底层是哈希表数据结构,线程是【同步】的 -->> 不可以存入null键、null值

效率较低,故被【HashMap】替代

----|HashMap 采用哈希表实现 -->> 【无序】

底层是哈希表数据结构,线程是【不同步】的 -->> 可以存入null键、null值

【要保证键的唯一性,需要覆盖hashCode()方法和equals()方法】

----|LinkedHashMap

【常用方法:】

添加: V put(K key,V value) 可以是相同的key值,但是添加的value值会覆盖前面的

putAll(Map m)

从指定映射中将所有映射关系复制到此映射中(可选操作)

删除: remove(Object key) 删除关联对象,指定key对象

clear() 清空集合对象

获取: value get(Object key) 可以用于判断键是否存在的情况。

判断: boolean isEmpty() 如果此映射不包含键-值映射关系【即长度为0】,则返回true,否则返回false

boolean containsKey(Object key)

判断集合中是否包含指定的key

boolean containsValue(Object value)

判断集合中是否包含指定的value

当指定的键不存在的时候,返回的是null

长度: int size() 返回此映射中的键-值映射关系数

9、在什么时候该使用什么样的集合?

Collection 当我们需要保存若干个对象的时候使用集合

-->> List 如果需要保留存储顺序、并且重复元素时,使用List

-->> 如果查询较多,使用ArrayList;

如果存取较多,使用LinkedList;

如果需要线程安全,使用Vector。

-->> Set 如果不需要保留存储顺序,并且要去掉重复元素时,使用Set

-->> 如果需要将元素排序,使用TreeSet;

如果不需要排序,使用HashSet 【HashSet比TreeSet效率高】

如果需要保留存储顺序,同时要过滤重复元素,使用LinkedHashSet。

10、自定义对象时为什么要重写toString()和equals()方法?

因为Object是自定义类的父类,Object类中的toString()方法返回的是哈希值;

Object类中的equals()方法比较的是对象的地址值。

【去除集合中重复的元素】

代码如下:

public class Demo{

public static void main(String[] args){

ArrayList arr = new ArrayList();

Person p1 = new Person("jack",20);

Person p2 = new Person("rose",18);

Person p3 = new Person("rose",18);

arr.add(p1);

arr.add(p2);

arr.add(p3);

System.out.println(arr);

ArrayList arr2 = new ArrayList();

for(int i=0;i

Object obj = arr.get(i);

Person p = (Person)obj;

if(!arr2.contains(p)){

arr2.add(p);

}

}

System.out.println(arr2);

}

}

class Person{

private String name;

private int age;

public Person(){

}

public Person(String name,int age){

this.name = name;

this.age = age;

}

public String getName(){

return name;

}

public void setName(String name){

this.name = name;

}

public int getAge(){

return age;

}

public void setAge(int age){

this.age = age;

}

public int hashcode(){

return this.name.hashCode() + age*37;

}

public boolean equals(Object obj){

if(!(obj instanceof Person)){

return false;

}

Person p = (Person)obj;

return this.name.equals(p.name) && this.age = p.age;

}

public String toString(){

return "name:" + this.name + "age:" + this.age;

}

}

11、Vector: 多线程安全、但是效率低 ---->> 描述的是一个线程安全的ArrayList。

特有的方法:

void addElement(E obj) 在集合末尾添加元素

E elementAt(int index) 返回指定角标的元素

Enumeration element() 返回集合中的所有元素,封装到Enumeration对象中

Enumeration接口:

boolean hasMoreElements() 测试此枚举是否包含更多的元素

E nextElement() 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素

【代码如下:】

public static void main(String[] args){

Vector v = new Vector();

v.addElement("aaa");

v.addElement("bbb");

v.addElement("ccc");

// System.out.println(v.elementAt(2));

Enumeration ens = v.elements();

while(ens.hasMorreElements()){

System.out.println(ens.nextElement());

}

}

12、Iterable: 是Collection的父接口,实现Iterable的类可以进行迭代,并且支持增强for循环

该接口只有一个方法,用于返回集合迭代器对象! 【获取迭代器的方法iterator()】

piblic interface Iterable

Iteratoriterator():该类主要用于遍历集合对象,并描述了遍历集合的常见方法

boolean hasNext() 判断集合中是否有元素,如果有元素可以迭代,就返回true。

E next() 返回迭代的下一个元素。

如果没有下一个元素,调用next()会抛出 -->> NoSuchElementException

void remove() 从迭代器指向的集合中移除迭代器返回的最后一个元素

【Iterator的for循环、清空】

public class Demo{

ArrayList list = new ArrayList();

// 增加:add() 将指定对象存储到容器中

list.add("计算机网络");

list.add("现代操作系统");

list.add("java编程思想");

list.add("java核心技术");

list.add("java语言程序设计");

System.out.println(list);

for(Iterator it = list.iterator();it.hasNext();){

// 迭代器的next()方法返回值类型是Object,所有要记得【类型强转】

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

System.out.println(next);

it.remove();

}

}

【细节一:如果迭代器的指针已经指向了集合的末尾,那么如果再调用next()会返回NoSuchElementException异常】

【细节二:如果调用remove()之前没有调用next()方法是不合法的,会抛出IllegalStateException异常】

【细节三:当一个集合在循环中即使用引用变量操作集合,又使用迭代器操作集合对象,会抛出ConcurrentModificationException异常】

13、为什么next()方法的返回值类型是Object呢?

为了可以接收任意类型的对象

如果返回的时候不知道是什么类型的,就定义为object

14、Iterator和ListIterator有什么关系?

ListIterator是Iterator的子接口,是List集合特有的迭代器。

Iterator在迭代时,只能对元素进行获取【next()】和删除【remove()】的操作;

ListIterator在迭代list集合时,还可以对元素进行添加【add(obj)】和修改【set(obj)】的操作。

15、List集合特有的迭代器ListIterator

---->> public interface ListIterator extends Iterator

ListIteratorlistIteraotr()

----| Iterator

hasNext()

next()

remove()

----| ListIterator

add(E e) 将指定的元素插入列表(可选操作)。

该元素直接插入到next()返回的下一个元素的前面(如果有)

void set(E o) 用指定的元素替换next()或previous()返回的 【最后】 一个元素

hasPrevious() 逆向遍历列表,列表迭代器有多个元素,则返回true

previous() 返回列表中的前一个元素

16、HashSet是如何判断两个元素重复的?

通过hashCode()方法和equals()方法来保证元素的唯一性,add()方法返回的是boolean类型

【调用原理:HashSet集合在判断元素是否相同,先判断hashCode()方法,相同才会判断equals()方法;不相同不会调用equals()】

17、HashSet和ArrayList集合在判断元素时是否有相同的方法?

有:boolean contains(Object o)

HashSet使用hashCode()和equals()方法,ArrayList使用eqauls()方法。

18、给TreeSet指定排序规则:

方式一:【元素自身】具备比较性

元素自身具备比较性,需要元素实现【Comparable接口】,重写【compareTo方法】,

也就是让元素自身具备比较性,这种方式叫做元素的【自然排序】也叫做【默认排序】。

方式二:【容器】具备比较性

当元素自身不具备比较性,或者自身具备的比较性不是所需要的。

那么此时可以让容器自身具备。需要定义一个类实现【Comparator接口】,重写【compare方法】,

并将该接口的子类实例对象作为参数传递给【TreeSet集合】的【构造方法】。

注意:当Comparable比较方式和Comparator比较方式同时存在时,以【Comparator】的比较方式为主;

注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。

通过return 0 来判断唯一性。

19、为什么使用TreeSet存入字符串,字符串默认输出是按升序排列的?

因为字符串实现了一个接口,叫做【Comparable接口】,字符串重写了该接口的【compareTo()方法】,

所以String对象具备了比较性。

【自定义的元素(比如Person类、Book类)想要存入TreeSet集合,就必须实现Comparable接口,也就是要让自定义对象具备比较性】

【存入TreeSet集合的元素都要具备比较性:要实现Comparable接口、并重写该接口的compareTo()方法】

20、总结:

看到array,就要想到角标。

看到link, 就要想到first,last。

看到hash, 就要想到hashCode,equals.

看到tree, 就要想到两个接口。Comparable,Comparator。

21、TreeSet是如何保证元素的唯一性的?

通过【compareTo】或者【compare】方法来保证元素的唯一性。

当Comparable接口中的compareTo()函数返回值为【0】时,说明两个对象相等,此时该对象不会被添加进来。

22、使用TreeSet集合将字符串 String str = "8 10 15 5 2 7"; 的数值进行排序。

public class Demo{

public static void main(String[] args){

String str = "8 10 15 5 2 7";

String strs = str.split(" ");

TreeSet ts = new TreeSet();

for(int x= 0;x

int y = Integer.parseInt(strs[x]);

ts.add(y);

}

System.out.println(ts);

}

}

23、遍历Map集合的方式有哪些?

方式一:使用keySet

将Map转成Set集合【keySet()】,通过Set的迭代器【Iterator】取出Set集合中的每一个元素,

即Map集合中所有的键,再通过get()方法获取键对应的值

Setks = map.keySet();

Iteratorit = ks.iterator();

while(it.hasNext()){

Integer key = it.next();

String value = map.get(key);

}

方式二:通过values获取所有值,但是不能获取到key对象

Collectionvs = map.values();

Iteratorit = vs.iterator();

while(it.hasNext()){

String value = it.next();

}

方式三:Map.Entry -->> public static interface Map.Entry

通过Map中的entrySet()方法获取存放Map.Entry对象的Set集合 -->>

Set entrySet()

Set entrySet = map.entrySet();

Iterator it = entrySet.iterator();

while(it.hasNext()){

Map.Entryen = it.next();

}

Integer key = en.getKey();

String value = en.getValue();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值