泛型

来源:互联网 发布:php就业方向 编辑:程序博客网 时间:2024/05/17 20:31
#泛型定义类型
* 运用泛型最大好处是可以避免类型转型异常,泛型就是引用数据类型,在泛型中不能用基础数据类型如"int",只能用其类型的包如"Integer"
* 指定多个泛型class Person<T,V>
* 在声明时指定泛型类型,如果没指定就会编译时出现警告,但仍然可以执行,因为没指定类型就默认是Object类型
```java
public static void main(String[] args){
    //Person<String,int> p1 = new Person<String,int>("小李",5); error,不能用基础类型
    Person<String,Integer> p1 = new Person<String,Integer>("小李",5);
    System.out.println(p1.getName()+","+p1.getAge());
    }
}
class Person<T,V>{   //多个泛型
    private T name;
    private V age;
    public Person(T name, V age) {
        this.name = name;
        this.age = age;
    }
    public Person(){
    }
    public T getName() {
        return name;
    }
    public void setName(T name) {
        this.name = name;
    }
    public V getAge() {
        return age;
    }
    public void setAge(V age) {
        this.age = age;
    }
}
```
#泛型通配符
* "?"(一般用于传参)
* 当你不确定泛型类型时就可以用"?",extends代表只能是子类和本身,super代表只能是父类和本身
```java
public class FloodType2 {
    public static void main(String[] args) {
        Person<String,Object> p = new Person<String,Object>("chen",2); //这里若将String换成Object就会出错,而将Integer换成Object就可以
        new Person1().fun(p);
        //Person<Object,Object> p = new Person<String,String>("chen",":"); error,泛型中不能用父类接收子类
    }
}
class Person1{
    public void fun(Person<? extends String,? super Integer> p){ 
        System.out.println(p.getName()+" "+p.getAge());
    }
}
```
#泛型接口
```java
public class FloodType3 {
    public static void main(String[] args) {
    AA<String> a = new AA<String>("chen");
    BB b = new BB("ren");
    System.out.println(a.fun1());
    System.out.println(b.fun1());
    }
}
//实现接口有两种方式
interface A<T>{
    public T fun1();
}
class AA<T> implements A<T>{  //第一 种:在实例化对象时指明类型
    public T fun1(){
        return null;
    }
}
class BB implements A<String>{  //第二种:在继承时指明类型
    public String fun1(){
        return null;
    }
}
```
#泛型方法
```java
public class FloodType4 {
    public static void main(String[] args) {
        Test1 t = new Test1();
        Test1 t2 = new Test1();
        System.out.print(t.test("寝室号码:"));  //传入String类型
        System.out.print(t2.test(158));  //传入Integer类型
    }
}
class Test1{
    public<T> T test(T t){  //泛型广泛方法,在传参时确定类型,再返回此类型,注意:静态方法不能访问类上定义的泛型(静态随类加载而返回值还不确定,因此要报错)
        return t;
    }
}
```
#泛型数组
```java
public static void main(String[] args) {
    Test1 t = new Test1();
    Test1 t2 = new Test1();
    Integer[] i = {1,4,5,2};  //注意:一定不能用int来定义数组,因为泛型不能使用基本数据类型
    t.test1(i);
    t2.test2(i);
class Test1{
    public<T> void test1(T[] t){
        for (int i=0; i<t.length; i++){
            System.out.println(t[i]);
        }
    }
    public<T> T[] test2(T[] t){
        return t;
    }
}
```
#泛型嵌套
```java
public class FloodType5 {
    public static void main(String[] args) {
    //使用了FloodType1中的Person类,此类有两个泛型
    C<Person> c1 = new C<Person>(new Person<String,Integer>("chen",3));   //将Person类作为一种类型
    C<Person<String,Integer>> cc = new C<Person<String,Integer>>(new Person<String,Integer>("jun",4));  //这种方式更为直观,与上面是一样代码却更为繁琐
    }
}
class C<P>{
    public C(){
    }
    public<T,V> C(Person<T,V> p) {
        System.out.println(p.getName()+" "+p.getAge());
    }
}
```
#集合
* 类集合就是一个动态的对象数组,一般很少直接使用Collection ,一般直接使用它的子接口,这样功能明确
#List
* List接口扩充了collection,所以拥有更多的方法,使用更方便,可以重复,实现子类ArrayList
```java
public class Collection1 {
    public static void main(String[] args) {
        List<Person> list1 = new ArrayList<Person>();
        List<Person> list2 = new ArrayList<Person>();
        Person p1 = new Person("chengdu",2);
         //Person p2 = new Person("beijing",4);
        Person p3 = new Person("shanghai",1);
        Person p4 = new Person("tianjing",3);   
        System.out.println("添加对象");
        list1.add(p1);  //增加对象
        list1.add(new Person("beijing",4));
        System.out.println(list1);
System.out.println("在下标1处添加一组对象");
        list2.add(p3);
        list2.add(p4);
        list1.addAll(1,list2);  //在指定位置添加一组对象
        System.out.println(list1);
        System.out.println("移出第一个对象");
        list1.remove(0);    //移除对象
        System.out.println(list1);
        System.out.println("输出对象");
        for (int i=0; i<list1.size(); i++){
            System.out.println(list1.get(i));  //输出对象
        }
        System.out.println("将集合变为数组");
        Object[] o = list1.toArray();  //将集合变为数组
        for (Object a:o)
    System.out.println(a);
        System.out.println("用p2替换1位置上的对象");
        list1.set(1, p4);   //用指定对象替换指定位置对象
        System.out.println(list1);
        System.out.println("返回指定位置对象");
        System.out.println(list1.get(1));
        System.out.println("截取0到2的对象");
        List<Person> list3 = list1.subList(0, 2); //截取指定位置的对象
        System.out.println(list3);
        System.out.println("查找'p2'的位置");
        System.out.println(list1.indexOf(new Person("beijing",4)));   //查找指定对象位置,当查找这个实例对象时,会自动调用重写的equals和hashCode方法来判断是否有相等的实例,这也是为什么字符串为什么可以直接查找到而对象不行,因为String类也重写了这两个方法
        System.out.println("移除list1所有对象");
        list1.clear();  //移除全部对象
        System.out.println(list1);
        System.out.println("判断list1是否为空");
        System.out.println(list1.isEmpty()); //为空就返回true
    }
}
class Person{
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Person() {
    }
    public String getName() {
        return name;
    }
    public String toString() {
        return this.name + this.age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int hashCode() {   //返回唯一的哈希码
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    public boolean equals(Object obj) {  //判断两个实例是否相等
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
            } else if (!name.equals(other.name))
                return false;
        return true;
    }
}
```
#LinkedList
* 链表操作符,继承了Deque所以具有队列的特点,先进先出
```java
public class Collection2 {
    public static void main(String[] args) {
        LinkedList<String> list1 = new LinkedList<String>(); //创建一个链表
        list1.add("成都");
        list1.add("上海");
        list1.add("北京");
        list1.add("天津");
        System.out.println(list1);
        list1.addFirst("云南"); //在头部添加对象
        list1.addLast("桂阳");  //在后面添加对象
        System.out.println(list1);
        System.out.println(list1.element()); //查找头
        System.out.println(list1.peek());    //查找头,这两种方式都很少用
        System.out.println(list1.poll());    //查找头,然后删除,这种方式用的较多
        System.out.println(list1);
        int k = list1.size();
        for (int i=0; i<k; i++){      //注意:不要直接用list1.size(),因为循环一次"poll"就会删除一个对象,长度会发生改变,会导致异常或是输出不完整
            System.out.println(list1.poll());
        }
    }
}
```
#HashSet
* 采用散列存储(哈希算法就是计算散列存储位置的一种算法),所以是无序的,重复的只会出现一次(因为相同东西算出来的位置是一样的)
```java
public class Collection3 {
    public static void main(String[] args) {
        Set<String> s = new HashSet<String>();
        s.add("成都");
        s.add("上海");
        s.add("天津");
        s.add("广州");
        System.out.println(s);
        s.add("天津");
        System.out.println(s);  //如果是自己定义的类要求不能重复存储,则要重写equals和hashCode方法
    }
}
```
#TreeSet
* 采用有序存放,它会将输入的对象按一定的算法顺序来存储
```java
public class Collection3 {
    public static void main(String[] args) {
        TreeSet<String> s1 = new TreeSet<String>(); 
        s1.add("c");
        s1.add("b");
        s1.add("a");
        s1.add("d");
        System.out.println(s1);
        TreeSet<Person1> s2 = new TreeSet<Person1>(new MyCompartor());
        s2.add(new Person1("成都",5,4));
        s2.add(new Person1("天津",4,5));
        s2.add(new Person1("北京",5,3));
        //重写compareTo方法前
        //System.out.println(s2); error,由于采用的有序存放,系统会自动排序,但系统又无法知道如何排序这些对象,因此会出错,这时就需要在类里定义一个排序方法
        //重写compareTo方法后
            System.out.println(s2);
    }
}
//如果要对我们自己定义的对象排序的话该对象必须实现Comparable接口,并通过覆盖compareTo方法,定义排序规则
class Person1 implements Comparable<Person1>{
    private String name;
    private int age;
    private int score;
    public Person1(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    public Person1() {
    }
    public String getName() {
        return name;
    }
    public String toString() {
        return this.name + this.age + this.score;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    public int compareTo(Person1 o) { 
        if(this.age > o.getAge()){  
            return 1;  //返回1则是从小到大,返回-1则是从大到小
        }
        else if(this.age < o.getAge()){  //当比较一个不足以分辨出前后时,若没有定义比较下一个则会造成存放遗失
            return -1;
        }
        else if(this.score > o.getScore()){  //嵌套一个比较
            return 1;
        }
        else if(this.score < o.getScore()){
            return -1;
        }
        return 0;
    }
}
//若是无法更改类为其实现comparable接口时,就需要创建一个Comparator子类实现compare方法,然后在创建TreeSet实例时创建该实例
class MyCompartor implements Comparator<Person1>{
    public int compare(Person1 p1,Person1 p2) {
        if(p1.getAge() > p2.getAge()){  
            return 1;  
        }
        else if(p1.getAge() < p2.getAge()){
            return -1;
        }
        else if(p1.getScore() > p2.getScore()){  
            return 1;
        }
        else if(p1.getScore() < p2.getScore()){
            return -1;
        }
        return 0;
    }
}
```
#SortedSet接口
* 用于排序的接口,它的子类都是排序的,Treeset就是实现了它
```java
public class Collection4 {
    public static void main(String[] args) {
    SortedSet<String> s = new TreeSet<String>();
    s.add("成都");
    s.add("天津");
    s.add("上海");
    s.add("广州");
    s.add("桂阳");
    System.out.println(s);
    System.out.println(s.first()); //查看第一个对象
    System.out.println(s.hashCode()); //查询哈希码
    System.out.println(s.last()); //查询最后一个对象
    System.out.println(s.headSet("广州"));  //查询排在此对象前面的对象,不包括此对象
    System.out.println(s.tailSet("天津"));  //查询排在此对象后面的对象,包括此对象
    System.out.println(s.subSet("天津", "成都"));  //查询两对象之间的对象,包括前者对象,不包括后者对象
    }
}
```
#迭代器
```java
Iterator<Person> ip = list2.iterator(); //迭代器:集合的迭代输出
ListIterator<Person> lip = list2.listIterator(); //若想从后往前输出就必须用Iterator的子接口listIterator,只对List有用
while (ip.hasNext()){    //判断后面是否有元素
    //System.out.println(ip.next().getName()); 查看下个元素姓名
    //System.out.println(ip.next().getAge()); 若是想查看同一个元素的姓名和年龄,一定不能这么写,因为这行代码代表是下下个元素的年龄了,解决办法就是保存元素
    Person p = ip.next();
    System.out.print(p.getName());
    System.out.print(p.getAge());
}
System.out.println();
while (lip.hasNext()){   //要从后往前必先从前往后
    System.out.print(lip.next());
}
System.out.println();
while (lip.hasPrevious()){  //判断前面是否有元素
    System.out.print(lip.previous());
}
System.out.println();
```
#Map
* Map接口主要用于查询
```java
Map<String,String> m = new HashMap<String, String>();//创建一个Map,存储的是相对应对象,无序
Map<String,String> m1 = new TreeMap<String,String>();//按照key对数据排序,如果是自己定义的类就必须实现Comparable<>接口
m.put("haoren", "3");  //输入key,value值
m.put("huanren","4");
m.put("buren","2");
System.out.println(m.get("haoren"));  //查询key对应的value值
if (m.containsKey("huanren")){    //判断是否有此key存在
    System.out.println("有坏人");
}
else{
    System.out.println("没有坏人");
}
if (m.containsValue("2")){   //判断是否有此value存在
    System.out.println("有2");
}
else{
    System.out.println("没有2");
}
Set<Map.Entry<String, String>> s = m.entrySet();   //先要转换成Set
Iterator<Map.Entry<String, String>> it = s.iterator(); //然后调用迭代器进行输出,输出是按一定的标准
while (it.hasNext()){
    System.out.println(it.next());
}
List<String> l = new ArrayList<String>();  //为集合添加全部对象
Collections.addAll(l, "haoren" , "huairen", "shangren");  //collections是集合工具类
System.out.println(l);
Collections.reverse(l);  //将集合对象反转
System.out.println(l);
Collections.sort(l); //排序
System.out.println(l);
System.out.println(Collections.binarySearch(l, "shangren"));//binarySearch是查找对象位置,调用binarySearch之前, 需对列表进行升序排序sort(all)。如果没有对列表进行排序,则结果是不明确的
Collections.replaceAll(l, "huairen", "haoren");//将指定对象替换成指定对象
System.out.println(l);
Collections.swap(l, 0, 2);
System.out.println(l);//将指定对象互换
```
0 0