搜索热点


Java第九课

何轩伟 2023-11-23 189 11/23
  1. Collection、Set、List、Queue接口

Collection、Set、List、Queue是Java中的四种接口,它们都属于Java集合框架的一部分。Collection是所有集合类的根接口,Set接口继承了Collection接口,并且不允许集合中包含重复的元素List接口也继承了Collection接口,但是允许集合中包含重复的元素,并且可以通过索引来访问集合中的元素;Queue接口则继承了Collection接口,但是它是一个队列,支持在队列头部插入元素,在队列尾部删除元素。

Collection根接口包含了:

add添加

contains包含

boolean 判断是否为空

Iteartor 迭代器

remove 移除

int size()索引大小

具体解释:Collection接口提供了多个方法来操作集合元素,其中包括add、contains、isEmpty、iterator、remove和size。add方法用于向集合中添加元素,contains方法用于判断集合中是否包含指定元素,isEmpty方法用于判断集合是否为空,iterator方法返回一个迭代器用于遍历集合中的元素,remove方法用于从集合中移除指定元素,size方法返回集合中元素的个数。这些方法的使用可以帮助我们更加方便地操作集合。

2.List接口支持索引访问,适用于有序但元素可能重复的集合。

ArrayList在底层会创建一个新的内存数组来存储数据,这意味着当需要添加或移除元素时,需要重新分配内存并复制元素。这样的操作会导致性能下降,因此如果需要频繁添加或移除元素,建议使用LinkedList。LinkedList使用链表来存储元素,可以快速添加或移除元素,但是访问元素的性能较差。因此,在选择数据结构时,需要根据具体的需求来进行选择。

 

LinkedList是一种链表结构,它提供了一组专门用于处理集合中第一个和最后一个元素的方法。

LinkedList底层实现是一个双向链表,每个节点都包含指向前一节点和后一节点的引用。这种数据结构使得在LinkedList中插入和删除元素更加高效,因为只需要改变相邻节点的引用即可。同时,LinkedList也支持随机访问,但是由于需要遍历整个链表(一个一个数过去),所以效率相对较低。

实例OddEven.java

import java.util.*;

 

public class OddEven {

//对参数list进行初始化

private static void initial(List<Integer> list,int size){

Random random=new Random(1);

for (int i=0;i<size;i++){

list.add(random.nextInt(10000000));

 

}

}

 

//    private static void removeEven(List<Integer> list){

//        for(int i=list.size()-1;i>=0;i--){

//            if(list.get(i) % 2==0){

//                list.remove(i);

//            }

//        }

//    }

 

private static void removeEven(List<Integer> list){

Iterator<Integer> iterator=list.iterator();

int current;

while (iterator.hasNext()){

current=iterator.next();

if(current % 2==0){

iterator.remove();      //用迭代器来提高性能

}

}

}

 

public static void main(String[] args) {

final int SIZE=10000000;

List<Integer> list=new LinkedList<>();

initial(list,SIZE);

long start=System.currentTimeMillis();

removeEven(list);

long end=System.currentTimeMillis();

System.out.println(end-start);

}

}

综上所述

ArrayList的性能较慢是因为每次对数组进行修改时,它都会创建一个新的数组来进行修改,导致重复操作。

LinkedList的性能较慢是由于其在访问元素时需要遍历整个链表(不会记录索引,每次都要从头加上数),而不像ArrayList可以通过索引直接访问元素。此外,LinkedList还需要额外的内存空间来存储节点间的指针信息。

迭代器会记录索引,这意味着它可以跟踪当前正在处理的元素的位置。(比如当这次数到5,下次访问位置10时不需要从1开始而是从5开始)通过使用迭代器,我们可以简化代码并提高程序的可读性和可维护性。

所以我们要根据程序不同要求来选用ArrayList或LinkedList。

3.Set接口

Set接口继承了Collection接口,类似于数学中的集合,具有无序性和非重复性。

例如{2,3}={3,2},这两个集合在数学中是相等的。

填充因子是一个用于动态数组或哈希表等数据结构中的参数。它表示在何时进行扩容操作,即当数据元素的数量达到容量的一定比例时,就会自动扩容以增加容量。这个比例就是填充因子。一般情况下,填充因子的取值范围为0到1之间。例如,当填充因子为0.75时,表示当数据元素的数量达到容量的75%时,就会进行扩容操作。这样可以避免频繁扩容,提高数据结构的性能。

set是一种数据结构,可以支持add和remove操作。使用add操作时,可以根据索引添加元素。而使用remove操作时,只能通过元素值来移除元素,因为set中元素是不可以重复的。这意味着,如果要添加一个已经存在的元素,它将不会被添加到set中(返回false)。同样地,如果要移除一个不存在的元素,它也不会产生任何影响。

HashSet在底层会维护一个数组,用来存储元素的位置。当元素被添加到HashSet中时,HashSet会根据元素的哈希值确定该元素在数组中的位置。如果该位置已经存在元素,那么HashSet会维护一个链表,将新元素添加到该链表的末尾。当需要查找元素时,HashSet首先根据元素的哈希值找到该元素在数组中的位置,然后遍历该位置上的链表,直到找到目标元素或者链表结束。这种设计可以使HashSet在添加、查找元素时具有较高的效率。

使用HashSet储存字符串时,输出顺序不保证与添加顺序相同。但是,如果使用LinkedHashSet,则可以按照添加顺序输出。

4.TreeSet接口

如果要使用TreeSet,其参数类型必须实现Comparable接口,否则需要在TreeSet对象上添加一个比较器。

(使用TreeSet时,如果参数类型没有实现Comparable接口,那么需要在TreeSet对象上添加一个比较器,否则会抛出ClassCastException异常。这是因为TreeSet是一个有序的集合,它需要对元素进行比较来确定它们的顺序。如果元素没有实现Comparable接口,那么就需要提供一个比较器来帮助TreeSet进行比较。比较器可以通过实现Comparator接口来创建,并将其传递给TreeSet的构造函数或使用setComparator()方法设置。)

实例TestTreeSet.java

import java.util.Comparator;

import java.util.TreeSet;

 

class Employee implements Comparable<Employee> {

int id;

double salary;

 

public Employee(int id, double salary) {

this.id = id;

this.salary = salary;

}

 

public int getId() {

return id;

}

 

public double getSalary() {

return salary;

}

 

@Override

public String toString() {

return "Employee{" +

"id=" + id +

", salary=" + salary +

'}';

}

 

@Override

public int compareTo(Employee o) {

return this.id-o.id;

}

}

 

public class TestTreeSet {

public static void main(String[] args) {

TreeSet<Employee> ts = new TreeSet<>(new Comparator<Employee>() {       //优先输出

@Override

public int compare(Employee o1, Employee o2) {

return (int) (o1.getSalary()- o2.getSalary());

}

});

ts.add(new Employee(2,20000));

ts.add(new Employee(1,25000));

ts.add(new Employee(3,18000));

System.out.println(ts);

}

}

当使用compareTo()方法和Comparator进行排序时,如果两者都存在,Java会优先使用Comparator进行排序,而不是使用对象自身的compareTo()方法。这是因为Comparator可以提供更灵活的排序方式,而且可以对任何类进行排序,而不需要修改类本身的代码。因此,在使用Java集合框架进行排序时,我们可以根据需要选择使用compareTo()方法或Comparator进行排序。

5.Map接口

Map接口是一个Java集合框架中的接口,它表示一种映射关系,即一组键(key)和对应的值(value)之间的映射。Map集合中的每个元素都包含了一个键值对(key-value pair),其中键唯一且不可重复,它用来标识该元素;值可以是任何类型的Java对象,可以重复,用来表示该元素对应的信息。

Map集合中提供了一系列操作键值对的方法,包括添加、删除、修改、查询等。常见的实现类有HashMap(性能最高)、TreeMap(自动排序,但键的类型必须实现Comparable接口)、LinkedHashMap等。

  • put(Object key, Object value):将指定键与指定值相关联,如果key已经存在,则用新的value替换旧的value,并返回旧的value。
  • get(Object key):返回指定键所映射的值,如果该键不存在,则返回null。
  • remove(Object key):移除指定键所映射的值,并返回该键对应的value。
  • containsKey(Object key):判断该Map中是否包含指定的键。返回的是布尔值(true/false)
  • containsValue(Object value):判断该Map中是否包含指定的值。返回的是布尔值(true/false)
  • size():返回该Map中键值对的数量。

实例TestMap.java

import java.util.*;

 

public class TestMap {

public static void main(String[] args) {

Map<String, String> map = new HashMap<>();

map.put("南通", "0513");

map.put("北京", "010");

map.put("南京", "025");

map.put("上海", "010");

//        map.remove("南通");

 

//        System.out.println(map.containsValue("0513"));

 

for (String city : map.keySet()) {      //keySet得到所有键构成的数学集

System.out.println(city);

}

 

Collection<String> postCodes = map.values();            //得到所有的值构成的集合

for(String code:postCodes){          //通过迭代器来迭代

System.out.println(code);

}

System.out.println(map);

}

 

}

请注意以上的注释部分,有相关代码说明

 

keySet()方法返回一个包含映射中所有键的 Set 集合

values()方法返回一个包含映射中所有值的 Collection 集合

entrySet()方法返回一个包含映射中所有键值对的 Set 集合;通过getKey获取键,getValue获取值

- THE END -
Tag:
最后修改:2023年11月23日
0

非特殊说明,本博所有文章均为博主原创。