六大区别 (重载与重写顺序表和链表Comparable和Comparator抽象类和接口super和thisArrayList和LinkedList)

Posted 鸢也

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了六大区别 (重载与重写顺序表和链表Comparable和Comparator抽象类和接口super和thisArrayList和LinkedList)相关的知识,希望对你有一定的参考价值。

区别

一、重载与重写

重载(overload):在一个类里面我们需要用一个函数同时兼容多种参数的情况, 我们就可以使用到方法重载 。在同一个方法内,方法名称相同,但是传入参数不同,这个就可以根据传入的参数来判断调用的到底是哪一个方法。重载大大增强了方法的功能性。[继承的时候,不一定就在同一个类里面了]

1.1方法的重载

class OverwriteDemo {
    void print(int i) {
        System.out.println("打印整型值:"+i);
    }
    void print(String i) {
        System.out.println("打印字符串类型值:" +i);
    }
    void  print(String s1,String s2) {
        System.out.println("打印字符串类型值:"+s1+";字符串类型值2:"+s2);
    }
}

public class Test {
    public static void main(String[] args) {
        OverwriteDemo overwriteDemo=new OverwriteDemo();
        overwriteDemo.print(12);
        overwriteDemo.print("123");
        overwriteDemo.print("字符串1","字符串2");
    }
}

1.2重载的规则

针对同一个类:

1、方法名相同

2、方法参数不同(参数个数或者参数类型)

3、方法的返回值类型不影响重载

1.3方法的重写 (覆盖,覆写)

同重载不同,重写(Override)是发生在两个类中的,且两个类是继承关系或者实现关系,同时方法签名完全相同!也就是说,方法名称和传入蚕食要完全一致。重写是java实现运行时多态的方式,这种通过对象类型而非定义类型去匹配实现方法的方式极大地提升了程序的开发效率和扩展性,同事也让程序更加易于维护。

重写使用==@Override== 注解注释,使用该注释编辑器会在编译时就检查该方法是否符合重写的条件,避免以为是重写却因出现导致该方法只是重载的尴尬情况发生。

想了解更详细重写 请转到 这个链接!!!!!

1.4 重写的规则:

重写:

1、方法名相同

2、方法的返回值相同

3、方法的参数列表相同

1.5 小结

区别重载(overload)重写(override)
概念方法名称相同,参数的类型及个数不同方法名称、返回值类型、参数的类型及个数完全相同
范围一个类继承关系
限制没有权限要求被覆写的方法不能拥有比父类更严格的访问控制权限

二、顺序表和链表

顺序表:底层是数组,数组的优点就是顺序表的优点,所以顺序表比较适合查找和修改,只要给定下标就可以找到这个数据并且可以修改;

链表:每个数据是由节点组织,链表适合插入和删除,他只需要通过节点修改执行就好。 关于链表的习题讲解可以点 这个链接 !!!

三、Comparable和Comparator

3.1 comparable

源码:

public interface Comparable<T> {
     public int compareTo(T o);
}

ComparaTo比较当前对象与指定对象的顺序

 @Override
    public int compareTo(Students o) {
        return this.age-o.age;
    }

this是当前对象;

o:是指定的对象比较

ComparaTo的源码:

 if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

也可以理解为当前对象大于,等于,小于返回1,0,-1:

 @Override
public int compareTo(Student o) {
    
    if(this.age > o.age) {
            return 1;
        }else if(this.age == o.age) {
            return 0;
        }else {
            return -1;
    }
}

3.2Comparator

源码:

public interface Comparator<T> {
     int compare(T o1, T o2);
}

compare用法:

class Studens {.........}
class AgeComparator implements Comparator<Students> {
    @Override
    public int compare(Students o1, Students o2) {
        return o1.getAge()-o2.getAge();
    }
}

public class Test {
    public static void main(String[] args) {
        Students[] students=new Students[3];
        students[0]=new Students("yuenye",12,20);
        students[1]=new Students("xiaoming",22,18);
        students[2]=new Students("weichi",50,32);
        AgeComparator ageComparator=new AgeComparator();
        Arrays.sort(students,ageComparator);
        System.out.println(Arrays.toString(students));
    }

Comparator也称之为比较器,可以通过compare指定里面的比较规则;

所以就引出了他两的区别:

3.3小结

1、Comparable也称内比较器,对类的侵入性强,Comparable里面的类都是自己跟自己比较,在自定义中的数组排序,如要排序就可以用到Comparable,但是要在这个数组进行另一种设定排序的时候就会改变原有类里面的代码,不够灵活.

@Override
    public int compareTo(Student o) {
        return (int)(this.score-o.score);
        //return this.name.compareTo(o.name);
        //return o.age-this.age;
        /*if(this.age > o.age) {
            return 1;
        }else if(this.age == o.age) {
            return 0;
        }else {
            return -1;
        }*/
    }

Comparator称外在比较器,对类的侵入性弱,不需要修改类本身,只需要修改比较器的比较规则,如要进行其他比较规则直接重写比较器即可;这也算是对Comparable不足的增强,扬长补短;

2.Comparable重写的是compareTo;

​ Comparator重写的是compare;

四、抽象类和接口

4.1 抽象类

1、用abstract修饰

2、抽象类可以包含字段,成员方法,和普通方法规则一样

3、不能被final和private修饰;

4、不能被实例化;

5、extends维护

6、普通类继承抽象类,那么普通类里面所有的抽象方法都要被重写;

4.2 接口

1、用interface修饰;

2、接口里面不能有普通方法,只能有抽象方法;

3、接口当中的成员变量,可以用publlic static final修饰;

4、不能被实例化;

5、一个类用implements实现n个接口;

6、接口和接口之间的关系时extends来维护;

详细的语法规则可以看 这个链接 !!!!

五、super和this

super关键字一般用于继承中,在构造函数和需要用到父类属性和方注的时候使用

大多数书上this写的是代表当前对象,其实是错误的,应该是代表当前对象的引用,想看原因可以 点击这个链接 !!!

六、ArrayList和LinkedList

ArrayList 和 LinkedList 是 List 接口的两种不同实现。

ArrayList底层是数组,LinkedList底层是一个双向链表,区别主要是他们不同方法使用和不同的时间复杂度。

6.1ArrayList:

1、get (int index) 方法时间复杂度是O(1),找到下标即可

2、boolean add(E e)方法,默认是放到这个数组最后的位置,还要考虑扩不扩容,不扩容时间复杂度就是O(1),默认数组大小变为10,需要扩容的话,需要扩容的话,扩容方式就是1.5倍扩容,add的源码最后还有个Arrays.copyOf(),最后还要把原数组复制到新数组中,就会耗时了;

//ArrayList 的add方法的源码
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
方法解释
ArrayList()无参构造
ArrayList(Collection<? extends E> c)利用其他 Collection 构建 ArrayList
ArrayList(int initialCapacity)指定顺序表初始容量
 List<Integer> list = new ArrayList<>();
 ArrayList<Integer> list2 = new ArrayList<>(14);
 ArrayList<Integer> list3 = new ArrayList<>(list);//new ArrayList<>()

6.2LinkedList:

1、get (int index) 方法时间复杂度是O(n),因为要遍历整个链表。

2、boolean add(E e)方法时间复杂度是O(1),因为是链表直接放最后就好了

方法解释
LinkedList()无参构造
LinkedList(Collection<? extends E> c)利用其他 Collection 构建 LinkedList
LinkedList<Integer> list = new LinkedList<>();
LinkedList<Integer> list2 = new LinkedList<>(new ArrayList<>());

6.3 小结

需要注意的是ArrayList和LinkedList在内存的使用上是不同的,LinkedList是双向链表,所以会存储前序和后续元素地址,所以LinkedList开销会比较大,但是ArrayList就没有这样的开销。另外ArrayList占用的内存用add方法的时候就已经默认是10了,而LinkedList不需要指定大小。

以上是关于六大区别 (重载与重写顺序表和链表Comparable和Comparator抽象类和接口super和thisArrayList和LinkedList)的主要内容,如果未能解决你的问题,请参考以下文章

C中线性表和链表的区别

线性表——顺序表和链表

顺序表和链表的基本操作,用C语言实现!

顺序表和链表的区别

数据结构之顺序表和链表的区别

ArrayList和LinkedList的区别?顺序表和单链表的区别?数组和链表的区别?