Effective Java学习--第21条:用函数对象表示策略

搞ACM大多数是使用C++,用java开发后总感觉对数据处理及输入输出控制不适应,仔细一想,其实是java没有指针的锅。在C++中,如果要实现结构体的自定义排序是非常简单的。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <set>
using namespace std;
typedef long long ll;

struct Student{
    int id;
    char name[20];
};

Student students[100];

bool cmp(Student a,Student b)
{
    return a.id<b.id;
}
int main()
{
    students[0].id = 5; strcpy(students[0].name,"wanghui");
    students[1].id = 3; strcpy(students[1].name,"zhangsan");
    students[2].id = 2; strcpy(students[2].name,"lisi");
    students[3].id = 4; strcpy(students[3].name,"linyifeng");
    students[4].id = 1; strcpy(students[4].name,"houzhenjie");

    sort(students,students+5,cmp);
    for(int i=0;i<5;i++)
    {
        printf("%d:%s\n",students[i].id,students[i].name);
    }

    return 0;
}

通过设置cmp来达到根据id自定义排序的效果。

而java中我一开始以为并没有类似的方法,想要实现类自定义排序必须要实现comparable接口重写compareTo()方法,然后放到list中排序,类数组的排序就没有用过。其实java也可以用函数对象来达到自定义排序的效果。

Student.java

package cczu.edu.test3;

public class Student{

    public int id;
    public String name;

    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + "]";
    }

}

Test

@Test
    public void test(){
        Student students[]=new Student[10];
        for(int i=0;i<5;i++){
            students[i] = new Student();
        }
        students[0].id = 5; students[0].name="wanghui";
        students[1].id = 3; students[1].name="zhangsan";
        students[2].id = 2; students[2].name="lisi";
        students[3].id = 4; students[3].name="linyifeng";
        students[4].id = 1; students[4].name="houzhenjie";
        Arrays.sort(students,0,5,new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.id-o2.id;
            }
        });
        for(int i=0;i<5;i++){
            System.out.println(students[i].id+":"+students[i].name);
        }
    }

这里为了跟C++代码对比,就没有使用javabean的规范。

结合ef之前讲过的单例模式,这里的比较器我是用匿名内部类实现的,每次排序都会new一次,如果想有更高的效率,可以讲比较器设置成单例模式。

时间: 2024-11-10 15:16:00

Effective Java学习--第21条:用函数对象表示策略的相关文章

Effective Java学习--第16条:复合优先于继承

在系统分析设计这门课中某王就不停地强调一点,就是ISA(is a 原则).都知道继承是面向对象的一大要素,但是哪里使用复合哪里使用继承,其实还是有讲究的. 可以简单的用ISA原则概括.有一个具备一定功能类,我们要对其功能进行拓展,到底是采用复合呢还是继承呢?当新类与旧类的关系是从属关系是,即cat is an animal,English book is a book,我们优先使用继承:当新类是旧类的组成部分之一时,即hand is a part of body,jiangsu is a par

Effective Java 学习笔记之创建和销毁对象

一.考虑用静态工厂方法代替构造器 1.此处的静态工厂方法是指返回指为类的对象的静态方法,而不是设计模式中的静态工厂方法. 2.静态工厂方法的优势有: a.使用不同的方法名称可显著地表明两个静态工厂方法的不同,而不像构造器,名字只能是类名. b.并不是每次调用静态工厂方法,都会重新构造一个新的对象. c.可以返回类型的子类型的对象. d.创建参数化类型的实例时,代码变得简洁了. 3.静态工厂方法的缺点有: a.类如果不含有公有的或者受保护的构造器,就不能被子类化(静态工厂方法的存在导致构造器存在的

Effective Java总结的78条

1.考虑用静态工厂方法代替构造器 2.遇到多个构造器参数时要考虑用构造器 3.用私有构造器或者枚举类型强化Singleton属性 4.通过私有构造器强化不可实例化的能力 5.避免创建不必要的对象 6.消除过期的对象引用 7.避免使用finalizer方法 8.重写equals方法时遵守通用约定 9.重写equals时总要重写hashCode 10.始终要重写toString 11.谨慎的重写clone 12.考虑实现Comparable接口 13.使类和成员的可访问性最小化 14.在共有类中使用

Effective java读书札记第一条之 考虑用静态工厂方法代替构造器

对于类而言,为了让客户端获取它资深的一个实例,最常用的方法就是提供一个共有的构造器.还有一种放你发,也应该子每个程序员的工具箱中占有一席之地.类可以提供一个共有的静态 工厂方法,它只是返回类的实例的静态方法. 类可以通过静态工厂方法类提供它的客户端(对象),而不是通过构造器.提这样做的好处有: 1.静态工厂方法与构造器不同的第一大优势在于,它们有名称.比如构造器BigInteger(int,int,Random)返回的BigInteger可能为素数,如果用名为BigInteger.probabl

Effective C++:条款21:必须返回对象时别妄想返回其reference

(一) 一定要避免传递一些references去指向其实并不存在的对象. 看下面这个类: class Rational { public: Rational(int numerator = 0, int denominator = 1); private: int n, d; friend const Rational operator*(const Rational& lhs, const Rational& rhs); }; 这个函数不能返回引用, (二)在stack中分配local对

Effective Java 读书笔记(2创建和销毁对象)

第一章是引言,所以这里不做笔记,总结一下书中第一章的主要内容是向我们解释了这本书所做的事情:指导Java程序员如何编写出清晰.正确.可用.健壮.灵活和可维护的程序. 2.1考虑用静态工厂方法代替构造器 静态工厂方法与构造器相比有四大优势: (1)静态工厂方法有名称,具有适当名称的静态工厂方法易于使用.易于阅读: (2)不必每次在调用它们的时候都创建一个新的对象: (3)可以返回原返回类型的任何子类型的对象: (4)在创建参数化类型实例的时候,它们使代码变得更加简洁. 同时静态工厂方法也有两大缺点

EffectiveJava——用函数对象表示策略

有些语言支持函数指针.代理.lambda表达式,或者支持类似的机制,允许程序把“调用特殊函数的能力”储存起来并传递这种能力.这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为.比较器函数有两个参数,都是指向元素的指针.如果第一个参数所指的元素小于第二个参数所指的元素,则返回一个负整数:如果两个元素相等则返回零:如果第一个参数所指的元素大雨第二个,则返回一个正整数.通过传递不同的比较器函数,就可以获得各种不同的排列顺序.这正是策略模式的一个例子.比较器函数代表一种为元素排列的策略

Effective Java 学习笔记之第七条——避免使用终结(finalizer)方法

避免使用终结方法(finalizer) 终结方法(finalizer)通常是不可预测的,也是很危险的,一般情况下是不必要的. 不要把finalizer当成C++中析构函数的对应物.java中,当对象不可达时(即没有引用指向这个对象时),会由垃圾回收器来回收与该对象相关联的内存资源:而其他的内存资源,则一般由try-finally代码块来完成类似的工作. 一.finalizer的缺点: 1. 终结方法的缺点在于不能保证会被及时地执行. 及时执行finalizer方法是JVM垃圾回收方法的一个主要功

第21条:用函数对象表示策略

有些语言支持函数指针(function pointer).代理(delegate).lambda表达式(lambda expression),或者支持类似的机制,允许程序把“调用特殊函数的能力”存储起来并传递这种能力.这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为. Java中没有提供函数指针,但是可以用对象引用实现同样的功能.调用对象上的方法通常是执行该对象(that object)上的某项操作.然而,我们也可能定义这样一种对象,它的方法执行其它对象(other obje