Java第十六天(泛型、Set接口、可变参数、数组工具类、集合工具类)

72.泛型java

(1)概念面试

泛型就是在集合中指定存储的数据类型,并且只能存储这种类型,在List<类型>必需要指定, ArrayList<>能够指定也能够不指定。基本数据类不能做为泛型。数组

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Generic {
    public static void main(String[] args) {
        //指定集合中只能存储一种数据类型
        List<Person> list = new ArrayList<>();
        Person p=new Person("frank",12);
        Person p1=new Person("lisa",11);
        list.add(p);
        list.add(p1);
        List<Person> list1 = new ArrayList<>();
        //age的int类型自动转成Integer类型
        Student s=new Student("david",11,1);
        Student s1=new Student("mia",12,2);
        //指定存储person的集合中能够存储指定类型和它的子类
        list1.add(s);
        list1.add(s1);
        //指定存储person的集合中能够存储指定类型和存储它的子类的子集合
        list.addAll(list1);
        ////建立一个迭代器对象
        ListIterator<Person> personListIterator = list.listIterator();
        while(personListIterator.hasNext()){
            //得到到Person型
            Person next = personListIterator.next();
            System.out.println(next);
        }
    }
}

(2)自定义泛型安全

在自定义泛型时并发

语法:class/interface 类名/接口名 <T>{ide

 

}函数

T只是泛型的一个标准,使用什么字符均可以,可是都要大写,不要使用特殊字符,建议用T工具

自定义泛型类性能

public class GenericClass<T> {
    //定义一个泛型的属性
    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}
public class GenericClass1<T,E,Z> {
    //定义三个泛型的属性
    private T t;
    private E e;
    private Z z;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public E getE() {
        return e;
    }

    public void setE(E e) {
        this.e = e;
    }

    public Z getZ() {
        return z;
    }

    public void setZ(Z z) {
        this.z = z;
    }

    @Override
    public String toString() {
        return "GenericClass1{" +
                "t=" + t +
                ", e=" + e +
                ", z=" + z +
                '}';
    }
}
import java.util.Arrays;
import java.util.Date;

public class GenericTest {
    public static void main(String[] args) {
        //指定泛型是String
        GenericClass<String> g = new GenericClass<>();
        g.setT("eric");
        System.out.println(g.getT());
        //指定泛型是Integer
        GenericClass<Integer> g1 = new GenericClass<>();
        g1.setT(12);
        System.out.println(g1.getT());
        //指定泛型是Integer数组
        GenericClass<Integer[]> g2 = new GenericClass<>();
        g2.setT(new Integer[]{1,2,3});
        System.out.println(Arrays.toString(g2.getT()));

        //测试3个泛型
        GenericClass1<Person, Integer, Date> g3 = new GenericClass1<>();
        g3.setT(new Person("milk",12));
        g3.setE(1);
        g3.setZ(new Date());
        System.out.println(g3);
    }
}

73.加强for循环测试

在Jdk1.5之后出现了加强的for

对数组,集合来作遍历

语法:

for(数据类型 变量:集合变量){

///

}

数据类型是集合或者数组中的数的类型

import java.util.ArrayList;
import java.util.List;

public class ForDemo {
    public static void main(String[] args) {
        String[] str={"pop","qoq","mom","bob"};
        System.out.println("-------------数组遍历----------------");
        for (String s : str) {
            System.out.println(s);
        }
        List<String> list=new ArrayList<>();
        list.add("pop");
        list.add("bop");
        list.add("pop");
        list.add("pop");
        System.out.println("-------------集合遍历----------------");
        for (String s : list) {
            System.out.println(s);
            if(s.equals("bop")){
                s="bob";
            }
        }
        System.out.println("-------------普通for循环遍历----------------");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
            if(list.get(i).equals("bop")){
                list.add("mom");
            }
        }
    }
}

加强的for循环遍历不支持并发,不能够增长或者删除改变集合或者数组的长度会出现异常报错,可是能够对某个成分进行更改,编译运行灭有出现错误,可是对结果却没有任何影响

普通的for循环能够实现并发

 

74.Set接口

一个不包含重复元素的 collection。更确切地讲,set 不包含知足 e1.equals(e2) 的元素对 e1e2,而且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。

在全部构造方法以及 add、equals 和 hashCode 方法的协定上,Set 接口还加入了其余规定,这些规定超出了从 Collection 接口所继承的内容。出于方便考虑,它还包括了其余继承方法的声明(这些声明的规范已经专门针对 Set 接口进行了修改,可是没有包含任何其余的规定)。

对这些构造方法的其余规定是(不要奇怪),全部构造方法必须建立一个不包含重复元素的 set(正如上面所定义的)。

注:若是将可变对象用做 set 元素,那么必须极其当心。若是对象是 set 中某个元素,以一种影响 equals 比较的方式改变对象的值,那么 set 的行为就是不肯定的。此项禁止的一个特殊状况是不容许某个 set 包含其自身做为元素。

某些 set 实现对其所包含的元素有所限制。例如,某些实现禁止 null 元素,而某些则对其元素的类型全部限制。试图添加不合格的元素会抛出未经检查的异常,一般是 NullPointerException 或 ClassCastException。试图查询不合格的元素是否存在可能会抛出异常,也可能简单地返回 false;某些实现会采用前一种行为,而某些则采用后者。归纳地说,试图对不合格元素执行操做时,若是完成该操做后不会致使在 set 中插入不合格的元素,则该操做可能抛出一个异常,也可能成功,这取决于实现的选择。此接口的规范中将这样的异常标记为“可选”。

(1)HashSet

此类实现 Set 接口,由哈希表(其实是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类容许使用 null 元素。

此类为基本操做提供了稳定性能,这些基本操做包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例。所以,若是迭代性能很重要,则不要将初始容量设置得过高(或将加载因子设置得过低)。

注意,此实现不是同步的。若是多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这一般是经过对天然封装该 set 的对象执行同步操做来完成的。若是不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在建立时完成这一操做,以防止对该 set 进行意外的不一样步访问:

Set s = Collections.synchronizedSet(new HashSet(...));

此类的 iterator 方法返回的迭代器是快速失败 的:在建立迭代器以后,若是对 set 进行修改,除非经过迭代器自身的 remove 方法,不然在任什么时候间以任何方式对其进行修改,Iterator 都将抛出 ConcurrentModificationException。所以,面对并发的修改,迭代器很快就会彻底失败,而不冒未来在某个不肯定时间发生任意不肯定行为的风险。

注意,迭代器的快速失败行为没法获得保证,由于通常来讲,不可能对是否出现不一样步并发修改作出任何硬性保证。快速失败迭代器在尽最大努力抛出 ConcurrentModificationException。所以,为提升这类迭代器的正确性而编写一个依赖于此异常的程序是错误作法:迭代器的快速失败行为应该仅用于检测 bug。

特色:

1.元素惟一性

2.无序行

3.容许null存在一个

4.不是线程安全(效率高)

import java.util.HashSet;
import java.util.Set;

public class SetTest {
    public static void main(String[] args) {
        Set<String> set=new HashSet<>();
        set.add("玉米");
        set.add("花生");
        set.add(null);
        set.add(null);
        System.out.println(set);
    }
}

探究惟一性:

若是对象的hash值和equals都相等那么就是重复的对象。

import java.util.HashSet;

public class SetTest1 {
    public static void main(String[] args) {
        HashSet<Person> h=new HashSet<>();
        h.add(new Person("Bob",12));
        h.add(new Person("Vob",12));
        h.add(new Person("Sob",12));
        h.add(new Person("Bob",12));
        System.out.println(h);
    }
}

(2)LinkedHashSet

有顺序可是应用的很少

具备可预知迭代顺序的 Set 接口的哈希表和连接列表实现。此实现与 HashSet 的不一样以外在于,后者维护着一个运行于全部条目的双重连接列表。此连接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序 受在 set 中从新插入的 元素的影响。(若是在 s.contains(e) 返回 true 后当即调用 s.add(e),则元素 e 会被从新插入到 set s 中。)

(3)TreeSet

字符串的比较规则是先按照第一个字符来比较,若是一个字符串的第一个字符比另外一个字符串首字符大,那前者大。

compareTo方法返回的是整数便是前者大,返回负数是后者大,是0就是相等

类若是要实现比较的规则都会实现Comparable接口。能够重写compareTo方法自定义比较规则

public class Person implements Comparable{
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

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

    @Override
    public int compareTo(Object o) {
        int flag=1;
        if(o instanceof Person) {
            Person p=(Person)o;
            flag=this.age-p.age;
            if(flag==0){
                flag=this.name.compareTo(p.name);
            }
        }
        return flag;
    }
}
public class CompareToTest1 {
    public static void main(String[] args) {
        Person p=new Person("Abi",8);
        Person p1=new Person("Jinx",9);
        System.out.println( p.compareTo(p1));
    }
}

TreeSet的特色:

1.元素惟一性

2.可自定义排序的(所存储的对象必须实现Comparable接口覆写compareTo方法)

3.不容许null存在(每次添加都会做比较的)

4.不是线程安全

基于 TreeMapNavigableSet 实现。使用元素的天然顺序对元素进行排序,或者根据建立 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

此实现为基本操做(addremovecontains)提供受保证的 log(n) 时间开销。

注意,若是要正确实现 Set 接口,则 set 维护的顺序(不管是否提供了显式比较器)必须与 equals 一致。(关于与 equals 一致 的精肯定义,请参阅 ComparableComparator。)这是由于 Set 接口是按照 equals 操做定义的,但 TreeSet 实例使用它的 compareTo(或 compare)方法对全部元素进行比较,所以从 set 的观点来看,此方法认为相等的两个元素就是相等的。即便 set 的顺序与 equals 不一致,其行为也 定义良好的;它只是违背了 Set 接口的常规协定。

public class Student extends Person {

    public Student(String name, Integer age) {
        super(name, age);
    }
    private Integer stuNo;

    public Integer getStuNo() {
        return stuNo;
    }

    public void setStuNo(Integer stuNo) {
        this.stuNo = stuNo;
    }

    public Student(String name, Integer age, Integer stuNo) {
        super(name, age);
        this.stuNo = stuNo;
    }

    @Override
    public String toString() {
        return "Student{" +
                super.toString()+
                "stuNo=" + stuNo +
                '}';
    }
}
import java.util.Set;
import java.util.TreeSet;

public class TreeSetTest {
    public static void main(String[] args) {
        Person p=new Person("Abi",8);
        Person p1=new Person("Jinx",10);
        Student s=new Student("Mia",9,2);
        Set<Person> set= new TreeSet<>();
        set.add(p);
        set.add(p1);
        set.add(s);
        System.out.println(set);
    }
}

75.可变参数

可变参数定义的语法:数据类型...变量名

能够表明数组或者单个数的传递

可变参数方法的语法:

修饰符 返回值类型 方法名(数据类型...变量名){

}

若是调用的时候发现有正好能够匹配的方法就不会调用可变参数方法,若是调用方法的时候不存在正好匹配的方法则调用可变参数方法

public class DynamicParam {
    public int add(int...a){
        int s=0;
        for (int i = 0; i < a.length; i++) {
            s+=a[i];
        }
        return s;
    }
}
public class DynamicParamTest {
    public static void main(String[] args) {
        DynamicParam d=new DynamicParam();
        int s=d.add(12);
        int s1=d.add(12,13,15,100);
        int s2=d.add(new int[]{12,13,15,100});
        System.out.println(s);
        System.out.println(s1);
        System.out.println(s2);
    }
}

76.数组工具类Arrays

import java.util.Arrays;

public class ArraysTest {
    public static void main(String[] args) {
        int[] i={1,2,3,4,5,6};
        String s= Arrays.toString(i);
        System.out.println(s);
        Person[] p = new Person[2];
        p[0]=new Person("aa",3);
        p[1]=new Person("bb",4);
        String s1=Arrays.toString(p);
        System.out.println(s1);
    }
}

import java.util.Arrays;

public class ArraysTest1 {
    public static void main(String[] args) {
        Person[] p = new Person[4];
        //注意:对数组中的对象排序,数组中的对象必须实现Comparable接口
        p[0]=new Person("aa",3);
        p[1]=new Person("bb",5);
        p[2]=new Person("cc",1);
        p[3]=new Person("dd",4);
        Arrays.sort(p);
        System.out.println(Arrays.toString(p));
    }
}

注意不能把基本数据类型的数组转换成集合,若是传递了基本数据类型的集合,就会把数组的类型做为泛型,能够是包装类的数组,数组转换成的集合长度不可改变

import java.util.Arrays;
import java.util.List;

public class ArraysTest2 {
    public static void main(String[] args) {
        Integer[] i={1,2,3,4,5,6};
        List<Integer> integers = Arrays.asList(i);
        System.out.println(integers);
        //数组转换成集合的长度不可变UnsupportedOperationException
        //list.add(9);
    }
}

77.集合工具类Collections

面试题:Collection是集合的接口;Collections是集合的工具类

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsTest {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("Bob",12));
        list.add(new Person("Vob",8));
        list.add(new Person("Sob",13));
        list.add(new Person("Bob",5));
        System.out.println("--------集合倒置---------");
        Collections.reverse(list);
        System.out.println(list);
        System.out.println("--------集合顺序打乱---------");
        Collections.shuffle(list);
        System.out.println(list);
        System.out.println("--------集合排序---------");
        //能够排序的泛型的类必须实现Comparable接口或者使用外置的比较器
        Collections.sort(list);
        System.out.println(list);
        //Collection中只有Vector是线程安全的
        Collections.synchronizedList(list);
    }
}

public class ComparatorDemo implements Comparator<People> {
    @Override
    public int compare(People o1, People o2) {
        int flag=o1.getAge()-o2.getAge();
        if(flag==0){
            flag=o1.getName().compareTo(o2.getName());
        }
        return flag;
    }
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsTest1 {
    public static void main(String[] args) {
        List<People> list = new ArrayList<>();
        list.add(new People("Bob", 12));
        list.add(new People("Vob", 8));
        list.add(new People("Sob", 13));
        list.add(new People("Bob", 5));
        //根据指定比较器产生的顺序对指定列表进行排序。sort(List<T> list, Comparator<? super T> c) 
        Collections.sort(list,new ComparatorDemo());
        System.out.println(list);
    }
}

相关文章
相关标签/搜索