list的特殊排序方法

STL列表排序

 
本例演示了对list的特殊排序方法。
编程需求:
在原有代码基础进行更新,
需要对list进行排序,list保存的是指针,而排序的依据为指针指向对象的某一个属性。
分析:
list本身包含有sort方法,但是并不能满足要求,其排序方法是使用其元素的比较方法(<)进行比较排序,
如果list内部保存为对象,即可使用这个方法,但是,由于保存内容为指针,其按照指针大小进行比较,这并不是我们想要的结果。
同时,可以考虑利用标准sort方法: sort(list.begin(), list.end(), function), function为比较方法,但是,这是存在问题的,因为list不支持随机存储,就不能调用泛型编程的sort。
同时,可以考虑使用vector,可以达到我们的要求,但是,由于已有代码的原因,把list替换为vector代价比较高,而且由于原设计采用list,使用vector可能引入其他操作细节的问题,再不得已情况下才会考虑实用vector进行替代。
解决方法:
由于list的sort有重载方法:sort(greater);
greater是一个模版结构体。这个就是问题的解决关键。
========================================

由于编程需要,用到了stl的list的排序
但是排序又有特殊要求,并不能用list的默认排序方法(list.sort())。
本来打算用stl的泛型算法的sort
但是出现了这样的错误:list不支持stl 的泛型sort 算法,因为list不支持随机存储。
麻烦大了。
我的代码如下:
class MyTest
{
private:
    int m_order;
    int m_ID;
public:
    MyTest(int clssID, int order):m_ID(clssID), m_order(order)
    {
    }
    int GetOrder()
    {
        return m_order;
    }
    int GetID()
    {
        return m_ID;
    }
};

int main(int argc, char* argv[])
{

    list<MyTest*> testList;
        // 向添加元素(MyTest指针)
        .......
        // 此处就是对testList进行排序,排序标准为 指针指向对象的order
        // 在此处使用 testList.sort() 是不能达到要求的,其是按指针的值进行排序。
        // 而且不能使用sort(testList.begin(), testList.end(), 比较方法 ); 因为list不支持随机存储。
        // 如果为vector 就可以进行排序
    return 0;
}


解决方案:
list的sort有重载方法,为sort(greater<>());
在此重写greater的特例就可以解决问题。

 

template<>
struct std::greater<MyTest*>
{
    bool operator()( MyTest*_X,  MyTest* _Y) const
    {
        return (_X->GetOrder() > _Y->GetOrder());
    }
};

全部代码:
#include "stdafx.h"
#include <list>
#include <iostream>
#include <algorithm>
using namespace std;
class MyTest
{
private:
int m_order;
int m_ID;
public:
MyTest(int clssID, int order):m_ID(clssID), m_order(order)
{
}
int GetOrder()
{
return m_order;
}
int GetID()
{
return m_ID;
}
};


template<>
struct std::greater<MyTest*>
{
    bool operator()( MyTest*_X,  MyTest* _Y) const
    {
        return (_X->GetOrder() > _Y->GetOrder());
    }
};


void TestOut(MyTest* p)
{
    cout << p->GetOrder() << endl;
}

int main(int argc, char* argv[])
{
    list<MyTest*> testList;

    for(int i = 0; i < 10; i++)
    {
        testList.push_back(new MyTest(rand()%50),rand()%100);
    }
    testList.sort(greater<MyTest*>());
    for_each(testList.begin(), testList.end(), TestOut);
    return 0;
}
输出结果:
==============================
41
34
28
24
19
17
14
12
8
0
Press any key to continue
==============================
结果为降序排列(数值为随机数,多次运行出现结果可能不同)

但是如果我想要一个升序排列,就要把greater的内部重新实现,考虑到灵活性,我们把代码修改成这样:

enum GREATER_OP
    //新增加枚举类型,标明排序方式。
{
    GREATER_UP = 0,
    GREATER_DOWN = 1
};
template<>
struct std::greater<MyTest*>
{
    GREATER_OP op;
    bool operator()( MyTest*_X,  MyTest* _Y) const
    {
        bool retVal;
        switch(op)
        {
        case GREATER_UP:
            retVal = (_X->GetOrder() < _Y->GetOrder());
            break;
        case GREATER_DOWN:
            retVal = (_X->GetOrder() > _Y->GetOrder());
            break;
        default:
            retVal = (_X->GetOrder() > _Y->GetOrder());
        }
        return retVal;
    }
};


现在代码是这个样子:
#include "stdafx.h"
#include <list>
#include <iostream>
#include <algorithm>
using namespace std;
class MyTest
{
private:
int m_order;
int m_ID;
public:
MyTest(int clssID, int order):m_ID(clssID), m_order(order)
{
}
int GetOrder()
{
return m_order;
}
int GetID()
{
return m_ID;
}
};


enum GREATER_OP
{
    GREATER_UP = 0,
    GREATER_DOWN = 1
};
template<>
struct std::greater<MyTest*>
{
    GREATER_OP op;
    bool operator()( MyTest*_X,  MyTest* _Y) const
    {
        bool retVal;
        switch(op)
        {
        case GREATER_UP:
            retVal = (_X->GetOrder() < _Y->GetOrder());
            break;
        case GREATER_DOWN:
            retVal = (_X->GetOrder() > _Y->GetOrder());
            break;
        default:
            retVal = (_X->GetOrder() > _Y->GetOrder());
        }
        return retVal;
    }
};


void TestOut(MyTest* p)
{
    cout << p->GetOrder() << endl;
}

int main(int argc, char* argv[])
{
    list<MyTest*> testList;

    for(int i = 0; i < 10; i++)
    {
        testList.push_back(new MyTest(rand()%50, rand()%100));
    }

    greater<MyTest*>
        my_Greater;
    my_Greater.op = GREATER_UP;
    testList.sort(my_Greater);
    for_each(testList.begin(), testList.end(), TestOut);

    cout << "=====================" << endl;
    my_Greater.op = GREATER_DOWN;
    testList.sort(my_Greater);
    for_each(testList.begin(), testList.end(), TestOut);
    return 0;
}

 

 

 

///MSDN 如何解决此问题的:greater 和lessthan要同时定义,调用list.sort(lessthan());

//sort.cpp
//compiler options cl /GX sort.cpp
#include <iostream>
#include <algorithm>
#include <list>
using namespace std;

//#define WORKAROUND //Uncomment this line to work around the bug.

class CSort
{
public:
    CSort(int i) : m_i(i) { }
    int m_i;
};

struct PrintElements
{
   void operator()(CSort* pfi) const
   {
      cout << pfi->m_i << "/n";
   }
};

#ifdef WORKAROUND
template<>
struct std::greater<CSort*>  : public binary_function<CSort* ,CSort*, bool>
{
    bool operator()(const CSort* &x, const CSort* &y) const
    {
 return (x->m_i < y->m_i);
    };
};
#endif

// User-defined predicate function for sorting.
struct lessThan : public greater<CSort*>
{
    bool operator()(const CSort* &pfi1, const CSort* &pfi2) const
    {
 return pfi1->m_i < pfi2->m_i;
    }
};

void SortTest()
{
    list<CSort*> l3;
    l3.push_back(new CSort(11));
    l3.push_back(new CSort(01));
    l3.push_back(new CSort(21));
    l3.push_back(new CSort(14));
    l3.push_back(new CSort(41));
    list<CSort*>::iterator lfii = l3.begin();
    l3.sort(lessThan());
    for_each(l3.begin(), l3.end(), PrintElements());
    cout.flush();
}


int main(int argc, char* argv[])
{
    SortTest();
    return 0;
}
    

<think>好的,我现在需要帮助用户解决关于Java中List排序方法的问题。用户希望得到具体的示例,所以我得整理出不同的方法并给出代码例子。 首先,我得回忆一下Java中对List排序的常用方法。记得主要有三种方式:使用Collections.sort(),使用List自带的sort()方法,以及Java 8之后的Stream流排序。另外,用户提供的引用里提到了这些方法,特别是引用[2]和引用[4]提到了Stream流和自定义排序,引用[3]涉及到了空值处理和并行排序,这些可能需要涵盖进去。 接下来,我需要确保覆盖到不同版本的Java特性。比如,Collections.sort()是比较传统的方式,适用于Java 7及以前;List.sort()是Java 8引入的,更直观;Stream流排序也是Java 8的特性,适合函数式编程。此外,自定义比较器和Lambda表达式也是重点,特别是用户示例中提到了使用Comparator.comparing,这部分需要详细说明。 然后,考虑用户可能需要实际代码示例,所以每个方法都应该有一个简短的例子。比如,对于基本数据类型的排序,自定义对象的排序,以及降序排列的处理。同时,要注意处理可能的空值,如引用[3]中的例子,将null放在开头或末尾,这可能是一个高级用例,需要包括进去吗?用户的问题可能更基础,但为了全面性,可以简要提及。 另外,用户提供的引用中有提到并行流排序,这在处理大数据量时有用,引用[3]中的例子使用了parallelStream()。虽然用户的问题可能不涉及大数据,但作为一个优化点,可以简单提到,以展示更全面的知识。 还要注意代码的正确性。例如,在使用Stream排序时,需要collect收集结果,因为流操作不会改变原列表。而List.sort()会直接修改原列表,这点需要说明清楚,避免用户混淆。 然后,结构方面,应该分点列出每种方法,先介绍方法,再给示例代码。每个示例需要简洁,并附上注释说明。例如,Collections.sort()对整数列表排序,自定义对象按年龄排序,使用Lambda表达式等。 最后,生成相关问题,可能涉及性能分析、优化方法、应用场景等,参考用户提供的示例中的相关问题,结合排序方法的不同方面来提问,比如比较不同方法的效率,如何处理复杂排序等。 现在需要检查是否有遗漏,比如是否提到Comparator的不同用法,或者自然排序(实现Comparable接口),或者处理多条件排序。例如,先按年龄排序,再按姓名排序,这样的例子对用户可能有帮助。引用[2]中的示例使用了reversed()方法进行降序排列,这也是一个有用的点。 还要确保代码示例中的语法正确,比如使用正确的泛型,避免中文符号,正确导入包等。例如,用户提供的引用[2]中的代码可能有一些HTML转义字符,如<和>,在示例中需要转换为正常的尖括号。 总结一下,回答的结构应该是: 1. 使用Collections.sort()方法 a. 基本类型 b. 自定义对象(实现Comparable) 2. 使用List.sort()方法 a. 自定义Comparator(Lambda) 3. 使用Stream流排序 a. 升序和降序 b. 多条件排序 4. 特殊处理 a. 空值处理 b. 并行排序 每个部分附上代码示例,并引用相关的引用资料。例如,引用[2]中的Stream示例,引用[3]中的空值和并行处理。 最后,生成相关问题,如性能比较、优化技巧、多条件排序实现等,帮助用户深入理解。</think>### Java中List排序方法详解 以下是Java中List排序的4种常用方法及示例: #### 1. 使用`Collections.sort()`基础排序 ```java // 对基本类型排序 List<Integer> numbers = new ArrayList<>(Arrays.asList(5, 2, 9, 1)); Collections.sort(numbers); // 默认升序 System.out.println(numbers); // [1, 2, 5, 9] // 自定义对象排序(需实现Comparable接口) class Person implements Comparable<Person> { int age; String name; @Override public int compareTo(Person o) { return Integer.compare(this.age, o.age); // 按年龄升序 } } ``` #### 2. 使用`List.sort()`方法(推荐Java 8+) ```java // 使用Lambda表达式 List<String> names = Arrays.asList("John", "Alice", "Bob"); names.sort((a, b) -> a.compareTo(b)); // 字典序排序 // 方法引用实现降序 List<Integer> nums = new ArrayList<>(Arrays.asList(3, 1, 4, 2)); nums.sort(Comparator.reverseOrder()); // [4, 3, 2, 1] ``` #### 3. 使用Stream流排序(Java 8+) ```java // 创建对象列表 List<Person> people = Arrays.asList( new Person(25, "Wang"), new Person(20, "Li") ); // 单字段排序 List<Person> sorted = people.stream() .sorted(Comparator.comparing(Person::getAge)) // 按年龄升序 .collect(Collectors.toList()); // 多字段排序(年龄降序,姓名升序) List<Person> complexSorted = people.stream() .sorted(Comparator .comparingInt(Person::getAge).reversed() .thenComparing(Person::getName)) .collect(Collectors.toList()); ``` #### 4. 特殊场景处理 ```java // 空值处理(null放最后) List<String> listWithNulls = Arrays.asList("B", null, "A"); listWithNulls.sort(Comparator.nullsLast(String::compareTo)); // 并行流大数据排序(百万级数据) List<Integer> bigData = new ArrayList<>(/* 百万元素 */); List<Integer> parallelSorted = bigData.parallelStream() .sorted() .collect(Collectors.toList()); ``` ### 方法对比表 | 方法 | 特点 | 适用场景 | |--------------------|-----------------------------|---------------------| | Collections.sort() | 修改原集合,需实现Comparable | 简单对象排序 | | List.sort() | 更直观的链式调用 | Java8+环境 | | Stream排序 | 生成新集合,支持复杂排序逻辑 | 多条件排序/函数式编程 | | 并行流排序 | 利用多核提升性能 | 大数据量排序[^3] |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值