十五、集合框架

1.1集合介绍

1.1.1集合的概念

集合:就是一个存储数据的容器。

集合与数组一样,也是一个容器,与数组的区别:

\1. 元素:

数组中的元素只能是相同,集合中的元素是任意的(泛型)

数组中可以存储基本类型和引用类型,集合只能存储引用类型,基本类型需要包装

\2. 长度(元素个数):

数组是定长的,一旦初始化长度就不可以修改

集合长度可以修改,可以删除元素和添加元素

1.1.2集合的框架结构

1.collection集合

 

\2. Map集合的框架结构

 

 

1.2collection接口

常用方法

add(E e) :确保此 collection 包含指定的元素。

addAll(Collection<? extends E> c) : 将指定 collection 中的所有元素都添加到此 collection中。

clear() :移除此 collection 中的所有元素。

contains(Object o): 如果此 collection 包含指定的元素,则返回true。

containsAll(Collection<?> c) : 如果此 collection 包含指定 collection 中的所有元素,则返回 true。

equals(Object o) : 比较此 collection 与指定对象是否相等。

isEmpty() :如果此 collection 不包含元素,则返回true。

iterator() :返回在此 collection 的元素上进行迭代的迭代器。

remove(Object o) : 从此 collection 中移除指定元素的单个实例,如果存在的话。

removeAll(Collection<?> c) :移除此 collection 中那些也包含在指定 collection 中的所有元素。

retainAll(Collection<?> c) :仅保留此 collection 中那些也包含在指定 collection 的元素。

size() :返回此 collection 中的元素数。

toArray() :返回包含此 collection 中所有元素的数组。

注意:判断元素是否相同的方式在每种实现中是不一样的

1.1.3泛型

1.1.3.1什么是泛型

泛型就是可以表示一个广泛数据类型的类型参数(泛型只能表示引用类型),把数据类型作为参数来传递。泛型也叫参数化类型。

用途(对比使用Object):

\1. 提供类型检查

\2. 省略类型强制转化

泛型具体类型取决于实例化对象时传入的实际类型

1.3.2泛型的使用

泛型类

定义泛型类

泛型类 :具有一个或多个类型参数的类

\1. 类型参数用尖括号括起来,放在类名后面。泛型类可以有多个类型参数,通过逗号分隔

\2. 类定义中的类型参数指定方法的返回类型以及成员和局部变量的类型。

\3. 类型参数名称符合标识符命名规则,一般使用单字母大写形式。在Java类库中,使用变量E表示集合的元素类型,K和V分别表示表的关键字和值得类型。T、U、S表示任意类型

\4. 类型参数的界限可以用来限制类型变量的类型

*类型限制通过extends关键字实现,后面可以是类和接口,如果类和接口都有,需要将类放在第一个

注意:

\1. 泛型擦除:

虚拟机中没有泛型,只有普通的类和方法,泛型信息只存在于代码编译阶段,在进入

JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除

所有的类型参数都用他们的限定类型替换,没有限定类型就是Object

\2. 不能用基本类型实例化类型参数

Pair<int> p1 = new Pair<>(),这个表达式无效

\3. 运行时类型查询只能适用于原始类型

p1 instanceof Pair<T>,这个表达式无效

\4. 不能实例化参数化类型的数组

new Pair<String>[10],这个表达式无效

\5. 不能实例化类型变量

new T(),这个表达式无效;

\6. 不能使用泛型声明静态属性

private static T three,这个表达式无效;

static属性先于对象,泛型类型取决于创建对象时传入的实际类型,所以泛型不能声明静态属性

\7. 泛型类型必须匹配才可以传递

Pair<Object> pair=new Pair<String>() ,这个表达式无效;

Pair pair=new Pair<String>() ,这个是可以的,参数类型是Object

\8. 不能抛出或捕获泛型类的实例,异常类不能参数化类型

继承泛型类

泛型类可以被继承,但是在子类中需要确定参数类型或者继承类型参数

泛型方法

泛型方法,带有类型参数的方法

\1. 泛型方法可以定义在普通类中,也可以定义在泛型类中。

\2. 当调用一个泛型方法时,在方法名前的尖括号中放入具体的类型

\3. 可以放在静态或者非静态方法中

\4. 抽象泛型方法的实现可以是泛型的,也可以非泛型的

public static <标识符> 标识符 fun(标识符 参数名){

}

泛型接口

public interface 接口名<标识符>{

//泛型可以充当接口中方法的返回值

//泛型可以充当接口中方法的参数

}

受限泛型**(了解即可)**

通过泛型类、接口定义引用变量时可以进行类型限定:

<?>:表示任意类型

<? extends T>:表示T类或者T类的子类

<? super T>:表示T类或者T类的父类

泛型集合

泛型在集合中的应用,表示的是集合中元素的类型

1.3.3Iterator**迭代器**

迭代器的工作原理

通过一个内部类的实例保存迭代状态,可以遍历集合元素。

迭代器的使用

hasNext() 判断迭代器是否存在下一个元素可以迭代器

next() 迭代器迭代下一个元素

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

迭代器模式

代器模式(Iterator Design Pattern),也叫作游标模式(Cursor Design Pattern)。它用来遍历集合对象。这里说的“集合对象”也可以叫“容器”“聚合对象”,实际上就是包含一组对象的对象,如数组、链表。迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单**一。迭代器是用来遍历容器的,所以,一个完整的迭代器模式一般会涉及容器和容器迭代器**两部分内容。

为了达到基于接口而非实现编程的目的,容器又包含容器接口、容器实现类,迭代器又包含迭代器接口、迭代器实现类。迭代器类以成员内部类的方式存在于容器类中,容器中需要定义iterator()方法,用来创建迭代器。迭代器接口中需要定义hasNext()、currentItem()、next()三个最基本的方法。

相对于for循环遍历(foreach也是基于迭代器的),利用迭代器来遍历有下面三个优势:

迭代器模式封装集合内部的复杂数据结构(如:二叉树),开发者不需要了解如何遍历,直接使用容器提供的迭代器即可完成集合的遍历;

迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一;

迭代器模式让添加新的遍历算法更加容易,更符合开闭原则。除此之外,因为迭代器都实现自相同的接口,在开发中,基于接口而非实现编程,替换迭代器也变得更加容易。

List**接口**

常用方法

add(int index, E element) 在列表的指定位置插入指定元素(可选操作)。

addAll(int index, Collection<? extends E> c) 将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。

containsAll(Collection<?> c) 如果列表包含指定 collection 的所有元素,则返回true。

get(int index) 返回列表中指定位置的元素。

indexOf(Object o) 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

lastIndexOf(Object o) 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。

listIterator() 返回此列表元素的列表迭代器(按适当顺序)。

remove(int index) 移除列表中指定位置的元素(可选操作)。

set(int index, E element) 用指定元素替换列表中指定位置的元素(可选操作)。

subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和

toIndex(不包括)之间的部分视图。

List的特点

\1. 按照插入顺序存储,可以存储相同元素,可以通过下标访问集合元素

\2. List接口中可以使用独有的迭代器ListIterator,具有双向遍历的功能

List接口的实现类

ArrayList**类**

ArrayList类是List接口基于数组的实现。实现了所有可选列表操作,并允许包括null在内(可以有多null)的所有元素。

存储特点:

保持插入顺序,可以存储相同元素,可以通过下标访问集合元素,

存储结构:

数组

LinkedList**类**

LinkedList类是List接口的链表实现。实现所有可选的列表操作,并且允许放入所有元素(包括null)。

存储特点:

保持插入顺序,可以存储相同元素,可以通过下标访问集合元素,

存储结构:

双向链表

Vector(了解)

JDK1.0时集合框架中的实现,JDK1.2重写了整个集合框架,Vector实现了List,主要为了向后兼容才

保留下来,目前不建议使用。也是基于数组实现的,而且是线程安全的。

ArrayList与LinkedList,Vector比较:

\1. 功能基本相同

\2. 底层存储结构:ArrayList是数组,LinkedList是双向链表,Vector是数组

\3. Vector是JDK1.0时设计的集合,是线程安全的,非并发环境下效率低,ArrayList是线程不安全的,效率高,推荐使用ArrayList【Collections工具类中有相应的方法可以将ArrayList改为线程安全的】

\4. ArrayList查找遍历比较快,LinkedList插入删除比较快

Stack(了解)

Stack类表示后进先出(LIFO)的对象栈。是Vector的子类,也是JDK1.0的实现,目前推荐使用双端队列Deque的实现。

如: Deque<Integer> stack = new ArrayDeque<Integer>();

数组或链表暴露了太多的操作接口,操作上的确灵活自由,但使用时就比较不可控,自然也就更容易出错,当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就可以选“栈”这种数据结构。栈只支持两个基本操作:入栈push()和出栈pop()。

关键知识点默写

\1. 集合的概念:“集合对象”也可以叫“容器”、“聚合对象”,实际上就是包含一组对象的对象,如:数组、List、Set等

数组是长度固定的,集合长度可以变化。

数组能存储基本类型和引用类型,集合只能存储引用类型。

\2. Collection接口:List和Set的父接口,常用方法add()、remove()、clear()、contains()、iterator()

\3. 泛型:把类中使用的数据类型作为参数传递

定义泛型类、泛型方法、泛型接口

使用泛型类声明引用型变量、创建类对象、继承类时指定泛型的实际类型

\4. 迭代器:将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一

hasNext();

next();

remove();

\5. List:按照插入顺序存储,可以存储相同元素,可以通过下标访问集合元素

\6. ArrayList:基于数组的实现,适用在对元素查询、遍历操作,不适合插入和删除。

\7. LinkedList:基于双向链表的实现,适用在对元素插入和删除操作,不适合遍历和查找

\8. Vector:也实现了List,JDK1.0遗留下来的一个集合类,线程安全,不建议使用

\9. Stack: 先进后出,支持入栈、出栈

\10. Queue:后进先出,支持入队、出队

常见面试题

\1. ArrayList与LinkedList的区别

\1. 功能基本相同

\2. 底层存储结构:ArrayList是数组,LinkedList是双向链表,Vector是数组

\3. Vector是JDK1.0时设计的集合,是线程安全的,非并发环境下效率低,ArrayList是线程不安全的,效率高,推荐使用ArrayList【Collections工具类中有相应的方法可以将ArrayList改为线程安全的】

\4. ArrayList查找遍历比较快,LinkedList插入删除比较快

\2. Stack的存储特点是什么s

Stack类表示后进先出(LIFO)的对象栈。

\3. 如何遍历一个List

https://www.cnblogs.com/Soy-technology/p/10729569.html

十六、Set接口和Map接口

Set接口

继承自Collection,不可以存储相同的元素,不能通过下标访问

Set接口常用方法

  • add(E e):如果指定的元素不存在,则将其添加到Set集合中,否则返回false。

  • addAll(Collection<? extends E> c):将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。

  • clear() : 移除此 collection 中的所有元素(可选操作)。

  • contains(Object o) : 如果此 collection 包含指定的元素,则返回true。

  • isEmpty() : 如果此 collection 不包含元素,则返回true。

  • iterator(): 返回在此 collection 的元素上进行迭代的迭代器。

  • remove(Object o) :从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。

  • size() : 返回此 collection 中的元素数。

  • toArray() : 返回包含此 collection 中所有元素的数组。

Set常用实现类

HashSet

通过哈希表(直接使用的是HashMap)实现的Set,不可以存储相同的元素,不能通过下标访问,不保持插入顺序。允许使用null值(如果为null,则哈希码为0)

数据结构:哈希表

JDK 1.7:数组+链表

JDK 1.8:数组+链表+红黑树(一种自平衡二叉树),当桶中元素数量大于等于8时,转为红黑树

重复元素判断逻辑链表:hashCode相同,并且地址相同或equals相同

红黑树排序逻辑:比对hashCode,如果hashCode相同,而且元素类实现了Comparable,则使用Comparable的对比方法,没有实现Comparable接口则用System.identityHashCode比较对象地址。

identityHashCode返回的是原始的hasCode(Object中的hasCode方法,不是重写后的)。

示例:

public class Demo3 {
    public static void main(String[] args) {
        Set<Dog> set=new HashSet<>();
        Dog dog=new Dog(1);
        set.add(null);  
        set.add(dog);   
        set.add(dog);
        set.add(new Dog(1));
        set.add(new Dog(2));        
        Iterator<Dog> iterator=set.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        set.contains(new Dog(1));
    }
}
​
class Dog{
    private int code;
​
    public Dog(int code) {      
        this.code = code;
    }
    
    public int getCode() {
        return code;
    }
​
    @Override
    public String toString() {
        return "Dog [code=" + code + "]";
    }
​
    @Override
    public int hashCode() {     
        System.out.println("hashcode-->"+code);
        return code;
    }   
​
    @Override
    public boolean equals(Object obj) {
        Dog dog=(Dog)obj;
        System.out.println("equals-->this.code:"+code+" dog.getCode():"+dog.getCode());
        return dog.getCode()==this.code;
    }       
}
​

hashCode:返回一个整数值,要求同一个对象多次生成的哈希码相同。

equals:对比两个对象是否相同,equals比对相同的两个对象要返回相同的哈希码。

LinkedHashSet

继承自HashSet,在HashSet的基础上通过链表维护了元素的插入顺序,不可以存储相同的元素,不能通过下标访问,保持插入顺序

示例:

  public static void linkedHashSet1() {
    //Set<Integer> set = new HashSet<>();
    Set<Integer> set = new LinkedHashSet<>();
​
    set.add(5);
    set.add(5);
    set.add(4);
    set.add(6);
    set.add(8);
​
    for(Integer temp:set){
      System.out.println(temp);
    }
  }

TreeSet集合

基于红黑树(一种自平衡二叉树)的Set实现,元素是排序保存的。排序逻辑需要通过元素实现Comparable接口或者独立实现Comparator接口提供给TreeSet。不允许null值。

示例:

public class Demo4 {
​
    public static void main(String[] args) {
        //Set<Student> set = new TreeSet<>(new StudentComparator());
        
        TreeSet<Student> set = new TreeSet<>();
​
        set.add(new Student(6));
        System.out.println("------------------");
​
        set.add(new Student(5));
        System.out.println("------------------");
        set.add(new Student(1));
        System.out.println("------------------");
        set.add(new Student(3));
        
        System.out.println("------------------");
        set.add(new Student(4));
        
        
        System.out.println("------------------");
        set.add(new Student(2));
        
        
        Iterator<Student> iterator=set.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }   
        
    }
​
}
​
//独立的比较器
class StudentComparator implements Comparator<Student> {
​
    @Override
    public int compare(Student o1, Student o2) {
        System.out.println("o1.getCode():" + o1.getCode() + "  o2.getCode():" + o2.getCode());
        return o1.getCode() - o2.getCode();
    }
​
}
​
//实现Comparable接口,实现比对逻辑
class Student implements Comparable<Student>  {
    //学号
    private int code;
    
    public int compareTo(Student o) {
        return code - o.getCode();
    }
​
    public Student(int code) {
        this.code = code;
    }
​
    public int getCode() {
        return this.code;
    }
​
    @Override
    public String toString() {
        return "Student [code=" + code + "]";
    }
​
}

SortedSet接口

TreeSet除了实现了Set接口外,还实现了SortedSet接口。SortedSet继承自Set接口

SortedSet接口中常用的方法:

  • first():返回此 set 中当前第一个(最低)元素。

  • last():返回此 set 中当前最后一个(最高)元素。

  • headSet(E toElement):返回此 set 的部分视图,其元素严格小于toElement。

  • tailSet(E fromElement):返回此 set 的部分视图,其元素大于等于fromElement。

  • subSet(E fromElement, E toElement):返回此 set 的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。

示例:

SortedSet<Student> subSet =set.subSet(new Student(3), new Student(4));
for(Student temp:subSet) {
    System.out.println(temp.toString());
}

随堂练习:

  1. 按照字母的长度来排列字符串 ,如果长度一样 按照编码顺序排列

Map接口

Map集合不同于List、Set,Map集合保存键值对,Map中不能包含重复的键,值可以重复。

Map接口的常用方法

clear() 从此映射中移除所有映射关系(可选操作)。

containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。

containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。

entrySet() 返回此映射中包含的映射关系的 Set 视图。

get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

isEmpty() 如果此映射未包含键-值映射关系,则返回 true。

keySet() 返回此映射中包含的键的 Set 视图。

put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。

putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。

remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

size() 返回此映射中的键-值映射关系数。

示例:

public static void map() {
    //创建集合
    Map<String, String> map = new HashMap<>();
    //1. 添加元素
    map.put("cn", "中国");
    map.put("usa", "美国");
    map.put("uk", "英国");
    map.put("kor", "韩国");
    map.put("cn", "中华人民共和国");//会把原来的值覆盖掉
​
    System.out.println("元素个数:" + map.size());
    System.out.println("打印:" + map.toString());
​
    //2. 通过key获取value
    System.out.println("通过key获取value:" + map.get("cn"));
​
    //3遍历
    //3.1 使用keySet遍历
    System.out.println("---------keySet()----------");
    Set<String> keySet = map.keySet();
    for (String key : keySet) {
      System.out.println(key + "..........." + map.get(key));
    }
​
    //3.2 使用values();
    System.out.println("---------values()---------");
    Collection<String> values = map.values();
    for (String value : values) {
      System.out.println(value);
    }
    //3.3 使用entrySet();
    System.out.println("---------entrySet()---------");
    Set<Map.Entry<String, String>> entrySet = map.entrySet();//Entry(映射对)
    for (Map.Entry<String, String> entry : entrySet) {
      System.out.println(entry.getKey() + "...." + entry.getValue());
    }
​
    //4判断
    //4.1 isEmpty
    System.out.println("判断isEmpty():" + map.isEmpty());
​
    //4.2 判断是否包含指定的key
    System.out.println("cn:" + map.containsKey("cn"));
​
    //4.3 判断是否包含指定的value
    System.out.println("韩国:" + map.containsValue("韩国"));
​
​
    //5. 删除
    map.remove("uk");
    map.clear();  
}

Map常用实现类

HashMap

基于哈希表的Map实现。此实现提供所有可选的映射操作,并允许使用null值和null键(如果key为null,则哈希码为0)。此类不保证kv的顺序。

存储特点: 元素以键值对形式存在,键不可以重复,值可以重复,可以快速的通过键查找到所对应的值。

Map集合的key,需要重写键所属的类的hashCode和equals方法即可。

示例:

public class Demo5 {
​
    public static void main(String[] args) {
        Map<String,Student> map=new HashMap<>();
        
        map.put("张三", new Student(1));
        
        map.put("李四", new Student(2));
        
        map.put("李四", new Student(3));
        
        System.out.println(map.size());
        
        System.out.println(map.get("李四"));
        
        System.out.println(map.containsKey("李四"));
        
        System.out.println("-------------1---------------");
        
        System.out.println(map.containsValue(new Student(3)));
        
        
        Set<Map.Entry<String,Student>> entrys=map.entrySet();
        
        for(Map.Entry<String,Student> entry:entrys) {
            System.out.println("key="+entry.getKey()+";value="+entry.getValue());
        }
    }
}
​
class Student{
    
    private int code;
    
    public Student(int code) {
        this.code = code;
    }
​
    public int getCode() {
        return this.code;
    }
​
        
    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }
​
    @Override
    public String toString() {
        return "Student [code=" + code + "]";
    }
​
}
​

LinkedHashMap

继承自HashMap,在HashSet的基础上通过链表维护了元素的插入顺序.

Properties

Properties 继承于 Hashtable,表示一个持久的属性集。属性列表中每个键及其对应值都是一个字符串。可以加载属性文件,用属性文件中的键值填充Properties 。

示例:

public static void main(String[] args) throws Exception {
    Properties properties = new Properties();
    properties.load(new FileInputStream("config.properties"));
    //使用ClassLoader从类路径中读取文件
    //properties.load(ClassLoader.getSystemResourceAsStream("config.properties"));
​
    String username = properties.getProperty("username");
}
  • FileInputStream中如果使用的是相对路径,是相对于系统属性 user.dir 指定的路径,默认也就是执行java命令的当前路径。Eclipse中默认是项目的根路径

  • load方法在读取属性文件时使用的字符编码是iso-8859-1(这是一个单字节编码),而且Eclipse中属性文件的默认字符编码就是 iso-8859-1, 如果输入中文字符会自动转码为unicode编码(\u****)。在文件编辑过程中,为了便于中文内容的输入,可以将属性文件的字符编码配置为utf-8,这样就可以正常展示中文字符,但是属性值中不要输入中文内容(注释中是可以的),否则读取后是乱码。

TreeMap

基于红黑树的Map实现,不允许key为null值。

排序原则同TreeSet

示例:

public class Demo5 {
    public static void main(String[] args) {
        //创建集合
        TreeMap<Person, String> treeMap=new TreeMap<>();
        Person p1=new Person("马云", 50);
        Person p2=new Person("李彦宏", 45);
        Person p3=new Person("马化腾", 40);
        Person p4=new Person("马云", 50);
        
        //1添加数据
        treeMap.put(p1, "杭州");
        treeMap.put(p2, "北京");
        treeMap.put(p3, "深圳");
        treeMap.put(p4, "shanghai");
        
        System.out.println("元素个数:"+treeMap.size());
        System.out.println(treeMap.toString());
        
        System.out.println("---------------------比较器--------------------");
        TreeMap<Person, String> treeMap2=new TreeMap<>(new Comparator<Person>() {
​
            @Override
            public int compare(Person o1, Person o2) {
                int n=o1.getAge()-o2.getAge();
                int n2=o1.getName().compareTo(o2.getName());
                return n==0?n2:n;
                
            }
        });
        treeMap2.put(p1, "杭州");
        treeMap2.put(p2, "北京");
        treeMap2.put(p3, "深圳");
        treeMap2.put(p4, "shanghai");
        
        System.out.println(treeMap2.toString());
        
    }
}

Hashtable

  • Hashtable线程安全的,而HashMap线程不安全的

  • Hashtable中不允许存在null的键和null值,但是HashMap中允许null的键和null值

Collections

Collections包含一系列操作Collection的静态方法。

1 、排序

static <T extends Comparable<? super T>> void sort(List<T> list) :对指定列表按升序进行排序。

示例:

ArrayList<Integer> list = new ArrayList<>();
list.add(-10);
list.add(5);
list.add(3);
list.add(7);
​
System.out.println(list);
Collections.sort(list);//默认升序
System.out.println(list);

2、将集合中的元素进行反转

static void reverse(List<?> list) :反转指定列表中元素的顺序。

Collections.reverse(list);

3、将集合元素打乱

static void shuffle(List<?> list) :使用默认随机源对指定列表进行置换。

4、 获取集合中的最大值、最小值

        /*
        static T max(Collection coll) 
          根据元素的自然顺序,返回给定 collection 的最大元素。
          
          static <T extends Object & Comparable<? super T>> 
        T min(Collection<? extends T> coll) 
          根据元素的自然顺序 返回给定 collection 的最小元素。 
        */
        int n1 = Collections.max(list);

5、替换

        /*
        static <T> boolean 
 replaceAll(List<T> list, T oldVal, T newVal) 
          使用另一个值替换列表中出现的所有某一指定值 
        */
        //原因:List集合是不排重的,使用新的元素将集合中出现的所有的旧的元素替换掉
        Collections.replaceAll(list,5,100);

6、统计指定元素在集合中出现的次数

        /*
        static int frequency(Collection<?> c, Object o) 
          返回指定 collection 中等于指定对象的元素数。 
        */
        int num = Collections.frequency(list,5);

7、二分法查找

        /*
        static <T> int 
 binarySearch(List<? extends Comparable<? super T>> list, T key) 
          使用二分搜索法搜索指定列表,以获得指定对象。 
        */
        //前提:必须是排好序的集合
        int index = Collections.binarySearch(list,-10);
​
        //注意:Collections工具类中的方法只操作Collection接口,主要操作的是List接口 

8、集合和数组的转换

1 数组转成集合
​
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
​
public class Demo2 {
    public static void main(String[] args) {
        //arrayToList();
        //listToArray();
         arrayToList2();
    }
    //1数组转成集合,集合不能做添加、删除操作
    public static void arrayToList() {
        String[] names= {"张三","李四","王五"};
        List<String> list=Arrays.asList(names);
        
        System.out.println("list:"+list);
        //添加
        //list.add("赵六");
        //删除
        //list.remove(0);
        //System.out.println("添加或删除之后list:"+list);
        list.set(0, "本伟");
        System.out.println("替换之后:"+list);
        
    }
    //2 集合转成数组
    public static void listToArray() {
        ArrayList<String> arrayList=new ArrayList<>();
        arrayList.add("苹果");
        arrayList.add("小米");
        arrayList.add("华为");
        arrayList.add("三星");
        
        //数组
        String[] arr=arrayList.toArray(new String[0]);
        System.out.println("--------遍历数组-------");
        for (String string : arr) {
            System.out.println(string);
        }
    }
    
    //3特殊
    public static void arrayToList2() {
        Integer[] nums= {10,20,5,8,9};
        List<Integer> arraylist=Arrays.asList(nums);
        for (Integer integer : arraylist) {
            System.out.println(integer);
        }
        
    }
    
}

关键知识点默写


  1. Collection 父接口 集合中常用方法:add() 、remove()、contains()、size()、 clear() 、iterator()

  2. List:特点:保持插入顺序,可按位置获取;可以重复;可以有多个null。

    • ArrayList:基于数组实现,适合遍历、按下标查找

  • LinkedList:基于双向链表的实现,适合插入、删除

    • Vector:老的集合,线程安全

  • Stack:栈,后进先出

    • Queue:后进先出,支持入队、出队

  1. Set: 特点:不一定保持插入顺序,不可以按位置获取元素,元素不能重复

    • HashSet:基于哈希表(数组+链表)实现的Set,判断元素是否重复的逻辑是,hashCode&&(地址或者equals方法)。可以有一个null。

      JDK8:如果桶中元素 大于8时,转为数组+红黑树(元素排序使用hascode,如果hascode相同,则再使用元素的compareTo方法,如果元素类没有实现Comparable接口,则对比原始hascode)

    • LinkedHashSet: 基于哈希表+链表实现的Set。继承自HashSet,在HashSet的基础上通过链表维护了元素的插入顺序。可以有一个null。

    • TreeSet:基于红黑树(一种自平衡二叉树)的Set实现,元素是排序保存的。排序逻辑需要通过元素实现Comparable接口或者独立实现Comparator接口提供给TreeSet。不能有null元素

  2. Map:Map集合保存键值对,Map中不能包含重复的键,值可以重复。

    • HashMap:存储结构:哈希表 ,无序 ,键不能重复;重复依据: hashCode() equals();key可以为null

    • LinkeHashMap:存储结构:哈希表 ,有序;key可以为null

    • Hashtable: jdk1.0的出现的集合,不能存储null键和null值,线程安全的。

    • Properties:Properties 继承于 Hashtable,表示一个持久的属性集。

    • TreeMap:存储结构:红黑树,一种自平衡二叉搜索树;key不可以为null

常见面试题

  1. 简述HashSet和LinkedHashSet之间的区别

    https://blog.csdn.net/u012888704/article/details/88410965?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.baidujsUnder6&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.baidujsUnder6

  2. TreeSet如果确定元素是否重复

补充:

List 有序可重复

  • 注意:基本数据类型不能作为泛型存在,如果需要在集合中存放基本数据类型数据,则使用其对应的包装类。

    • ArrayList:数组结构

    • 特点:查询(获取快速),插入和溢出效率很低 *使用ArrayList()(无参构造函数)创建list对象时,集合元素个数为0,添加第一个元素时 ,元素个数(长度)重新赋值为10,

    • 之后每次达到容量上限时,重新对长度扩容,扩容两为现长度的50%,如果值不是整数,则向下取整 * *常用方法:

    • size():获取集合中实际的元素的个数

    • add(e):向集合的末尾添加一个新的元素

    • get(index):获取集合中指定下标(index)的元素

    • addAll(list1):向当前集合中添加另一个集合的所有元素。另一个集合(list1)要求其泛型与当前集合的泛型相同或其子类

    • list.add(index,value);向当前集合中的指定位置添加元素,

    • clear();:清除当前集合中的元素,原理:将集合中的所有元素引用类型赋值为null;将size属性重新赋值为0.

    • remove():移除指定位置的元素

    • remove(对象):移除当前集合中第一个与指定对象相同的元素,然后将匹配位置之后的元素前移一位。

    • reamoveAll(集合):移除当前集合中指定集合所包含的所有元素,指定集合为list1

    • 注意:如果在当前集合中存在重复的多个元素,则在移除时将被全部移除 *

    • LinkedList:链表结构

    • 特点:插入移除快速(效率高),查询效率较低

泛型

泛型的定义:在类名称后面,使用尖括号("<>")进行包裹,内部写入某个或某几个大写字母被称为当前类泛型

  • 作用:对当前类中即将要使用的对象进行约束,只能使用泛型指定的类型

  • 泛型指定时机:创建当前类对象时指定

  • 泛型使用场景:当前类中可能有多种类型参与执行,但每个本类对象只能使用一种类型的情况

  • 默认字母:类一般为T。接口一般为E

  • 接口中,一般在参数列表中

Set 无序、不可重复

  • 注意:HashSet、TreeSet两个Set接口的实现类,底层使用HashMap、NavigableMap

  • HashSet: 使用Hash(哈希)算法,计算要添加的元素在集合中的位置

  • TreeSet:使用树形结构(字典顺序),对存入的元素进行排序

Map

map:表示集合,形式:键值对。键、值可以是任意类型。

  • 注意:1.键的类型一般为String,值一般不为null

  • 2.在map集合中,键不能重复 ,值只要键不相同,则可以重复

  • 3.map之恶能通过get方法获取键对应的值

  • HashMap:Map接口的实现类,使用hash算法确定键值对的位置

  • put(键,值);:表示将一个键值对映射存入Map集合中

  • 返回值:存储成功返回null,否则返回已经存在键所对应的值

  • 注意:如果键已经存在,则后面的印设关系会替换已经存在的映射关系(键相同,则后面会替换前面的)

  • get(键):表示获取指定键(key)所对应(映射)的值(value)

  • 注意:如果指定的键不存在,则返回null;

  • TreeMap: Map接口的实现类。使用字典顺序对所有的键进行排序

  • HashTable:里面的值不能为空

Map-->方法

//判断当前map对象中,是否包含指定的键,包含返回true;否则返回false boolean flag = map.containsKey("k2"); //判断当前map对象中,是否报刊指定的键的值,包含返回true;否则返回false boolean flag1 = map.containsValue("k2"); //比较两个map对象中的键值对是否一致;一致返回true,否则返回false boolean flag2 = map.equals(map1); //根据给定的键从当前map对象中查询,如果当前键存在则返回其映射值,如果不存在,则返回方法中提供的默认值 String str6 = map.getOrDefault("str6", "value6"); //如果当前Map对象中指定的键值对不存在,则将此键值对 存入Map中,返回值null,否则不存入,返回值为对印(映射)的值 String str7 = map.putIfAbsent("key7", "value7"); //溢出当前Map对这项中指定的键及其应设置,返回值为此键的映射值 String str8 = map.remove("key7"); //使用新的值替换当前Map对象中指定键映射的值,返回值为此键原映射值,如果指定键不存在,则返回null String str9 = map.replace("key4", "kitty");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新手菜鸟大白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值