美文网首页
Java 集合

Java 集合

作者: 小石头呢 | 来源:发表于2019-08-16 23:21 被阅读0次

集合主要技术

  • 了解Collection和Map
  • Collection接口
  • ArrayList类
  • HashSet类
  • HashMap类
  • Collections工具类
  • 泛型

一 .Collection和Map

Collection集合继承关系图 Map集合继承关系图

线程安全:多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

Collection

  • Collection是对象集合,有两个子接口 List 和 Set,ArrayList、Vector 、LinkedList是List的实现类

  • ArrayList 是线程不安全的, Vector 是线程安全的,这两个类底层都是由数组实现的。

  • LinkedList是线程不安全的,底层是由链表实现的。

  • ArrayList和LinkedList的操作基本一致;HashSet和LinkedHashSet的操作基本一致。

Map是键值对集合

  • HashTable和HashMap是 Map 的实现类。

  • HashTable是线程安全的,不能存储 null 值;HashMap 不是线程安全的,可以存储 null 值。

  • HashTable的子类Properties类表示了一个持久的属性集,用于小型数据的持久化保存。

二.Collection接口

  • 1.创建:由于接口不能用来实例化一个对象,所以我们实例化其子类,利用多态性接受来测试Collection接口的方法。创建的时候需要明确存放的内容是什么类型。
Collection<String> collection = new ArrayList();
  • 2.添加:直接在末尾添加指定对象或者添加某个集合的内容
//末尾添加
boolean add(E e);

collection.add("Jack");
collection.add("Mary");
System.out.println(collection);

输出:[Jack, Mary]

//添加一个集合
boolean addAll(Collection<? extends E> c);

collection.clear();//清空
Collection<String> collectionTemp = new ArrayList();
collectionTemp.add("Jack");
collectionTemp.add("Mary");

collection.addAll(collectionTemp);
System.out.println(collection);

输出:[Jack, Mary]
  • 3.移除:移除指定对象,移除指定集合内对象,除了指定集合内的元素外其余元素全部移除,按照指定条件移除
//移除指定对象
boolean remove(Object obj);

collection.remove("Jack");
System.out.println(collection);

输出:[Mary]

//移除指定集合对象
boolean removeAll(Collection<?> c);

Collection<Integer> collectionTemp1 = new ArrayList();
collectionTemp1.add(1);
collectionTemp1.add(2);
collectionTemp1.add(3);
Collection<Integer> temp = new ArrayList();
temp.add(1);
collectionTemp1.removeAll(temp);
System.out.println(collectionTemp1);

输出:[2, 3]

//除了指定集合内的元素外其余元素全部移除
boolean retainAll(Collection<?> c);

Collection<Integer> collectionTemp1 = new ArrayList();
collectionTemp1.add(1);
collectionTemp1.add(2);
collectionTemp1.add(3);
Collection<Integer> temp = new ArrayList();
temp.add(1);
collectionTemp1.retainAll(temp);
System.out.println(collectionTemp1);

输出:[1]

//按照指定条件移除
boolean removeIf(Predicate<? super E> p)

Collection<Integer> collectionTemp1 = new ArrayList();
collectionTemp1.add(1);
collectionTemp1.add(2);
collectionTemp1.add(3);
collectionTemp1.removeIf(obj -> obj > 2);
System.out.println(collectionTemp1);

输出:[1, 2]
  • 4.获取元素个数
int size();

System.out.println(collection.size());

输出:1
  • 5.判断一个元素是否包含另一个元素
boolean contains(Object obj);

if (collection.contains("Mary")) {
     System.out.println("有Mary");
}else {
     System.out.println("有Mary");
}

输出:有Mary
  • 6.判断是否为空
boolean isEmpty();

//判断是否为空
if (collection.isEmpty()){
   System.out.println("是空的");
}else{
   System.out.println("不是空的");
}

输出:不是空的
  • 7.判断两个集合是否相同
boolean equals(Object obj);

if (collection.equals(collectionTemp)){
    System.out.println("相同");
}else{
   System.out.println("不相同");
}
  • 8.转化成不可变的普通数组
//转化成为Object类型的不可变数组
Object[] toArray();

Object[] array1 = collectionTemp.toArray();
for (Object obj : array1) {
    System.out.print((String)obj);
}

输出:JackMary

//转化成为指定类型的不可变数组
<T> T[] toArray(T[] t);

Integer[] array2 = new Integer[collectionTemp.size()];
array2 = collectionTemp.toArray(array2);
for (String str : array2) {
    System.out.print(str);
}

输出:JackMary
  • 9.迭代器遍历:迭代器刚开始不指向第一个位置,下一个才是第一个位置
//获得当前集合的迭代器
Iterator<E> iterator();

//判断下一个位置是否有元素
boolean hasNext();

//指向下一个位置,并返回下一个位置的值
E next();

Iterator iterator = collectionTemp.iterator();
while (iterator.hasNext()){
    System.out.print(iterator.next());
}

//输出:JackMary
  • 10.清空集合
void clear();

collection.clear();
System.out.println(collection);

输出:[]

三.ArrayList

ArrayList实现了Collection接口,Collection有的方法ArrayList都有,并且在其基础上还有更多的方法。接下里说一下ArrayList比Collection多的方法。

1.创建

ArrayList<Integer> score = new ArrayList();

2.添加

  • Collection接口提供的方法
//添加指定对象
boolean add(E e);

//添加一个集合
boolean addAll(Collection<? extends E> c);
  • 新的方法:在指定索引位置添加对象
public void add(int offset, E e);
score.add(2);//末尾添加
score.add(0,3);//指定位置插入
System.out.println(score);

输出:[3, 2]

3.访问指定索引位置的元素

public E get(int offset);
System.out.println(score.get(0));

输出:3

4.修改指定索引位置元素

public E set(int offset, E e);
score.set(0,1);
System.out.println(score);

输出:[1, 2]

5.返回给定对象的索引值

//返回指定对象第一次出现的索引位置
public int indexOf(Object obj)

//返回指定对象最后一次出现的索引位置
public int lastIndexOf(Object obj)

6.返回给定集合某一块的子集合

public List<E> subList(int offset, int len)
System.out.println(score.subList(0,1));

输出:[1]

7.移除

  • Collection接口提供的方法
//移除指定对象
boolean remove(Object obj);

//移除指定集合对象
boolean removeAll(Collection<?> c);

//除了指定集合内的元素外其余元素全部移除
boolean retainAll(Collection<?> c);

//按照指定条件移除
boolean removeIf(Predicate<? super E> p)
  • 新的方法:移除指定索引位置对象
public E remove(int offset)
  • 混淆问题:操作是对象,为什么我们可以对基本类型进行操作呢。因为Java内部有装盒(例如:int->Integer)和拆盒(例如:Integer->int)的操作。
//删除指定位置的元素
score.remove(0);
System.out.println(score);
输出:[2]

//删除指定对象
score.remove((Integer) 2);
System.out.println(score);
输出:[]

8.排序

public void sort(Comparator<? super E> c)
  • 排序重点是创建一个比较器对象,首先说系统提供好的升序和降序比较器。
ArrayList<Integer> list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);

//降序
list.sort(Comparator.reverseOrder());
System.out.println(list);

//升序
list.sort(Comparator.naturalOrder());
System.out.println(list);

输出:
[6, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 6]
  • 根据想要比较的对象创建
list.sort(Comparator.reverseOrder());
System.out.println(list);

//升序
list.sort(Comparator.comparing(Integer::intValue));
System.out.println(list);

输出:
[6, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 6]
  • 自己创建一个类实现Comparator接口
class XLCompare implements Comparator{

    @Override
    public int compare(Object o1, Object o2) {
        int mo1 = (int)o1;
        int mo2 = (int)o2;

        return mo1 - mo2;
    }
}

list.sort(Comparator.reverseOrder());
System.out.println(list);

list.sort(new XLCompare());
System.out.println(list);

输出:
[6, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 6]
  • 使用匿名类完成:什么时候需要自己手动创建比较器,如果系统默认提供的方法不能完成我们的比较
list.sort(Comparator.reverseOrder());
System.out.println(list);

list.sort(new Comparator<Integer>() {
    @Override
    public int compare(Integer integer, Integer t1) {
        return integer-t1;
    }
});
System.out.println(list);

输出:
[6, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 6]
  • 使用Lambda 表达式
list.sort(Comparator.reverseOrder());
System.out.println(list);

list.sort((Integer i1,Integer i2)->i1-i2);
System.out.println(list);
  • 例子:比较两个自定义的对象
public class Person {
    String name;
    int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
}

class XLCompare implements Comparator{

    @Override
    public int compare(Object o1, Object o2) {
        Public p1 = (Public)o1;
        Public p2 = (Public)o2;
        
        if(p1.age != p2.age){
             return p1.age - p2.age;
        }else{
             return p1.name - p2.name;
        }
    }
}

ArrayList<Person> list = new ArrayList();

String[] names = {"张明","张杰","李明浩","李浩天","李隆基","李世明"};

for (int i = 0; i < names.length; i++) {
    Person person = new Person(names[i],i+30);
    list.add(person);
}

list.sort(new XLCompare());

四.HashSet

1.简述

  • Set里面元素不能重复,如果重复添加不进去;其内部使用HashMap来实现,键值对中键key不能重复。内部是通过计算每个key的hash值,是在对象的地址的基础上得到的值;Object类有一个方法public native int hashCode();用来返回hash值;切记重写类的equals方法一定要重写hashCode方法,hashCode和equals详解。Object类还有一个方法protected native Object clone() throws CloneNotSupportedException;用于复制对象,clone详解

  • Set是无序的,添加的顺序和存储的顺序无关;而ArrayList添加的顺序和存储的顺序有关。

  • Hash大部分的操作可以参照Collection接口。

  • HashSet内部的顺序是按照默认的顺序排列的;TreeSet则可以使用我们给定的顺序排列。

2.HashSet代码例子

HashSet<String> hashSet = new HashSet<>();

hashSet.add("java");
hashSet.add("java");
hashSet.add("jack");
hashSet.add("Android");
System.out.println(hashSet);
//[java, jack, Android]

hashSet.removeIf(element->element.compareTo("c") > 0);
System.out.println(hashSet);
//[Android]

3.TreeSet代码例子

  • 可以在TreeSet的构造方法中传入一个比较器Comparator,这又涉及到Comparator和Comparable两个接口的区别

  • Comparator 则是在外部制定排序规则,然后作为排序策略参数传递给某些类,例如ArrayList的sort方法,TreeSet的构造方法。

  • 自然排序需要类实现 Comparable,并且在内部重写 comparaTo 方法。Object类有一个用于比较的方法public boolean equals(Object var1) {return this == var1;},就需要类实现 Comparable。系统内部的类基本上都实现了Comparable接口,如果我们自定义的类需要比较,那么一定要实现 Comparable接口。

class Person implements Comparable{
    String name;
    int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //equals比较的是对象内部的内容
    //所有的对象要能参加比较,必须实现Comparable
    //接口compareTo方法
    //在compareTo中做具体的比较
    @Override
    public int compareTo(Object o) {
        //判断o对象是不是Person的一个对象
        if (o instanceof Person){
            //自己规定返回的策略
            if (this.age != ((Person) o).age){
                return this.age-((Person) o).age;
            }else {
                //年龄相同的情况下再比姓名
                return this.name.compareTo(((Person) o).name);
            }
        }else {
            return -1;
        }
    }
}
TreeSet<Integer> score = new TreeSet<>();

score.add(32);
score.add(45);
score.add(12);
System.out.println(score);
//[12, 32, 45]

//Lambda表达式方式
TreeSet<Person> persons = new TreeSet<>((Person p1,Person p2)->p1.compareTo(p2));

//匿名类方式
/*TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
    @Override
    public int compare(Person person, Person t1) {
        return person.compareTo(t1);
    }
});*/

Person p1 = new Person("仙王",18);
Person p2 = new Person("武帝",18);
Person p3 = new Person("开天",18);

persons.add(p1);
persons.add(p2);
persons.add(p3);

System.out.println(persons);

输出:[Person{name='仙王', age=18}, Person{name='开天', age=18}, Person{name='武帝', age=18}]

五.HashMap

一.概述

  • HashMap集合存储数据的特点:键key-值value

  • key不能重复,可以是任意的对象类型,通常使用字符串

二.方法

  • 1.创建对象:需要制定键和值得类型。
HashMap<String,Integer> score = new HashMap<>();
  • 2.添加键值对:添加的键值相同的情况,后面的默认更改值。
public V put(K key, V value)

添加一个HashMap

public void putAll(Map<? extends K, ? extends V> m)
//添加对象:键值对
score.put("Chinese",90);
score.put("English",88);
score.put("Math",100);

//相同的情况,默认更改其值
score.put("Chinese",95);
System.out.println(score);

输出:{English=88, Chinese=95, Math=100}
  • 3.获取键值对的个数
public int size()
System.out.println(score.size());

输出:3
  • 4.获取所有的key
public Set<K> keySet()
System.out.println(score.keySet());

输出:[English, Chinese, Math]
  • 5.获取所有的value
public Collection<V> values()
System.out.println(score.values());

输出:[88, 95, 100]
  • 6.获取一个键对应的值,如果key不存在,返回null
public V get(Object obj)
System.out.println(score.get("Chinese"));

输出:95
  • 7.返回包含映射的Set视图。
public Set<Entry<K, V>> entrySet()
System.out.println(score.entrySet());

输出:[English=88, Chinese=95, Math=100]
  • 8.键值对的遍历
//1.通过遍历key得到每一个key对应的值
for (String key : score.keySet()) {
    //通过key得到值
    int value  = score.get(key);
    System.out.println("key:"+key+" "+"value;"+value);
}

输出:
key:English value;88
key:Chinese value;95
key:Math value;100
//2.通过entrySet 得到Entry对象的集合
//一个entry管理一个键值对 getKey getValue
Set<Map.Entry<String ,Integer>> entrys = score.entrySet();
for (Map.Entry entry : entrys) {
    //得到entry对应的key
    String key = (String)entry.getKey();
    //得到entry对应的value
    Integer value = (Integer)entry.getValue();
    System.out.println("key:"+key+" "+"value;"+value);
}

输出:
key:English value;88
key:Chinese value;95
key:Math value;100
  • 9.删除制定键对应的映射关系
public V remove(Object obj)
score.remove("Chinese");
System.out.println(score);

输出:{English=88, Math=100}
  • 10.替换指定键对应的值
public V replace(K key, V value)
score.replace("English",90);
System.out.println(score);

输出:{English=90, Math=100}
  • 11.判断是否为空
public boolean isEmpty()
  • 12.清空所有映射关系
public void clear();

六.Collections工具类

  • 1.获取List中的最小值
List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);  
// 6  
System.out.println(java.util.Collections.min(intList));  
  • 2.获取List中的最大值
List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);  
// 99  
System.out.println(java.util.Collections.max(intList));  
  • 3.Shuffle方法可以使一个集合的元素乱序化。
List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);  
Collections.shuffle(intList);  
// 一次测试的结果  
// [6, 18, 33, 24, 99, 9]  
System.out.println(intList); 
  • 4. nCopies返回一个不可变列表组成的n个拷贝的指定对象。
// 生成一个由10个100组成的整数列表  
List<Integer> nCopiesList = Collections.nCopies(10, 100);  
//[100, 100, 100, 100, 100, 100, 100, 100, 100, 100]  
System.out.println(nCopiesList);  
  • 5.sort用于对集合排序。
List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);  
Collections.sort(intList);  
  • 6.binarySearch用于查找给定元素在给定数组的索引值。
List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);  
// 2  
System.out.println(Collections.binarySearch(intList, 18));  
  • 7.frequency获取某个元素在集合出现的次数。
List<String> testList = Arrays.asList("A", "B", "C", "D");  
int freq = Collections.frequency(testList, "A");  
// 1  
System.out.println(freq); 
  • 8.indexOfSubList返回指定源列表中第一次出现指定目标列表的起始位置。
int index = Collections.indexOfSubList(Arrays.asList("A", "B", "C"),  
Arrays.asList("B"));  
// Print 1  
System.out.println(index);  
  • 9.lastIndexOfSubList返回指定源列表中最后一次出现指定目标列表的起始位置。
int lastIndex = Collections.lastIndexOfSubList(  
        Arrays.asList("A", "B", "C", "B"), Arrays.asList("B"));  
// Print 3  
System.out.println(lastIndex);  
  • 10.reverse反转列表中的元素顺序。
List<String> reverseCandidate = Arrays.asList("A", "B", "C");  
Collections.reverse(reverseCandidate);  
// [C, B, A]  
System.out.println(reverseCandidate);  

七.泛型

1.泛型方法

  • 泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的<E>)。

  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。

  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。

  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。

public class GenericMethodTest{
   // 泛型方法 printArray                         
   public static < E > void printArray( E[] inputArray ){
      // 输出数组元素            
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] ){
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
 
        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组
 
        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}

输出:
整型数组元素为:
1 2 3 4 5 

双精度型数组元素为:
1.1 2.2 3.3 4.4 

字符型数组元素为:
H E L L O 

2.泛型类

  • 泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。

  • 和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。

  • 一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。

public class MyClass {

    public static void main(String[] args){
        //创建类,明确指定T指定的类型
        GenericTest<String> genericTest = new GenericTest<>();

        genericTest.test("java","oc");

        System.out.println(genericTest.a1);
    }
}

class GenericTest<T>{
    int age;
    T a1;
    T a2;

    public void test(T a1,T a2){
        this.a1 = a1;
        this.a2 = a2;

        System.out.println(a1.equals(a2));
    }
}

3.类型通配符

类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List<String>,List<Integer> 等所有List<具体类型实参>的父类。

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        getData(name);
        getData(age);
        getData(number);
       
   }
 
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
}

输出:
data :icon
data :18
data :314

相关文章

  • 一篇文章,全面解读Android面试知识点

    Java Java基础 Java集合框架 Java集合——ArrayList Java集合——LinkedList...

  • 收藏夹

    博文 Java 集合:Java 集合学习指南 Java 集合:Java 集合源码剖析 HashMap:HashMa...

  • Java 集合框架_开篇

    Java 集合框架系列 Java 集合框架_开篇Java 集合框架_ListJava 集合框架_ArrayList...

  • Java 集合框架_List

    Java 集合框架系列 Java 集合框架_开篇Java 集合框架_ListJava 集合框架_ArrayList...

  • 9、java集合

    1、什么是java集合 java集合是用来存储多个数据引用的数据类型。 2、java集合分类 java集合类在ja...

  • 【集合框架】

    集合框架(怎么实现、适用场景) hash相关 Java集合框架 Java集合框架综述Java集合框架面试问题集锦 ...

  • Java基础——集合体系Map详解

    Java基础——集合体系Map详解 上文中我们了解了集合体系中的单列集合:Java基础——集合以及Java集合——...

  • Java基础

    Java集合框架 一、Java集合类简介: Java集合大致分为四种体系:Set:无序、不可重复的集合List:有...

  • JavaSE集合类

    JavaSE集合类 概述 Java中集合类概述Java中数组与集合的比较Java中集合框架层次结构 Collect...

  • 集合系列(一):集合框架概述

    集合系列(一):集合框架概述 Java 集合是 Java API 用得最频繁的一类,掌握 Java 集合的原理以及...

网友评论

      本文标题:Java 集合

      本文链接:https://www.haomeiwen.com/subject/iioqsctx.html