并行过滤与过滤-归约
QtConcurrent::filter()、QtConcurrent::filtered() 和 QtConcurrent::filteredReduced() 函数可并行过滤序列(如QList )中的项目。 QtConcurrent::filter() 对序列进行就地修改,QtConcurrent::filtered() 返回一个包含过滤后内容的新序列,而 QtConcurrent::filteredReduced() 返回单个结果。
这些函数是 Qt Concurrent 框架的一部分。
上述每个函数都有一个阻塞版本,该版本返回最终结果,而不是QFuture 。使用方法与异步版本相同。
QStringList strings = ...;
// each call blocks until the entire operation is finished
QStringList lowerCaseStrings = QtConcurrent::blockingFiltered(strings, allLowerCase);
QtConcurrent::blockingFilter(strings, allLowerCase);
QSet<QString> dictionary = QtConcurrent::blockingFilteredReduced(strings, allLowerCase, addToDictionary);请注意,上述结果类型并非QFuture 对象,而是真实的结果类型(在此情况下,分别为QStringList 和QSet<QString>)。
优化包含
如果您包含<QtConcurrent> 头文件,整个Qt Concurrent 模块和整个Qt Core 模块都会被包含进来,这可能会增加编译时间和二进制文件的大小。要使用QtConcurrent::filter()、QtConcurrent::filtered() 和QtConcurrent::filteredReduced() 函数,您可以包含一个更具体的头文件:
#include <QtConcurrentFilter>并发过滤器
QtConcurrent::filtered() 接受一个输入序列和一个过滤函数。随后,该过滤函数将针对序列中的每个元素被调用,并返回一个包含过滤后值的新序列。
过滤函数必须采用以下形式:
bool function(const T &t);T 必须与序列中存储的类型相匹配。若应保留该项,函数返回true ;若应丢弃该项,则返回 false。
此示例演示了如何从QStringList 中保留所有小写字符的字符串:
bool allLowerCase(const QString &string)
{
return string.lowered() == string;
}
QStringList strings = ...;
QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings, allLowerCase);过滤器的结果可通过 `QFuture` 获取。有关如何在应用程序中使用 `QFuture ` 的更多信息,请参阅QFuture 和QFutureWatcher 中的文档。
若需就地修改序列,请使用 QtConcurrent::filter():
QStringList strings = ...;
QFuture<void> future = QtConcurrent::filter(strings, allLowerCase);由于序列是在原地修改的,因此 QtConcurrent::filter() 不会通过QFuture 返回任何结果。不过,您仍然可以使用QFuture 和QFutureWatcher 来监控过滤器的状态。
并发过滤与延续
调用 QtConcurrent::filtered() 的结果是一个包含多个结果的QFuture 。当将.then() 延续附加到此类QFuture 上时,请确保使用将QFuture 作为参数的延续,否则仅会处理第一个结果:
autokeepPositive= [](intval) {
returnval> 0;
};
QList<int>inputs {-1, 1, 2,-3, 5};
autobadFuture=QtConcurrent::filtered(inputs,keepPositive)
.then([](intval) {
qDebug() << val;
});
autogoodFuture=QtConcurrent::filtered(inputs,keepPositive)
.then([](QFuture<int>f) {
for(autor : f.results()) {
qDebug() << r;
}
});在此示例中,badFuture 只会打印一个结果,而goodFuture 则会打印所有结果。
并发过滤-归约
QtConcurrent::filteredReduced() 与 QtConcurrent::filtered() 类似,但它不会返回包含过滤后结果的序列,而是使用 reduce 函数将结果合并为单一值。
该 reduce 函数必须采用以下形式:
V function(T &result, const U &intermediate)其中 T 是最终结果的类型,U 是待过滤项的类型。请注意,reduce 函数的返回值和返回类型均不被使用。
请按如下方式调用 QtConcurrent::filteredReduced():
void addToDictionary(QSet<QString> &dictionary, const QString &string)
{
dictionary.insert(string);
}
QStringList strings = ...;
QFuture<QSet<QString>> dictionary = QtConcurrent::filteredReduced(strings, allLowerCase, addToDictionary);对于过滤函数保留的每个结果,都会调用一次 reduce 函数,该函数应将中间结果合并到result变量中。QtConcurrent::filteredReduced() 保证任何时候只有一个线程会调用 reduce,因此无需使用互斥锁来锁定 result 变量。QtConcurrent::ReduceOptions 枚举提供了一种控制归约操作执行顺序的方法。
其他 API 功能
使用迭代器代替序列
上述每个函数都有一个变体,该变体接受迭代器范围而非序列。其使用方式与序列变体相同:
QStringList strings = ...;
QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings.constBegin(), strings.constEnd(), allLowerCase);
// filter in-place only works on non-const iterators
QFuture<void> future = QtConcurrent::filter(strings.begin(), strings.end(), allLowerCase);
QFuture<QSet<QString>> dictionary = QtConcurrent::filteredReduced(strings.constBegin(), strings.constEnd(), allLowerCase, addToDictionary);使用成员函数
QtConcurrent::filter()、QtConcurrent::filtered() 和 QtConcurrent::filteredReduced() 接受指向成员函数的指针。成员函数的类类型必须与序列中存储的类型匹配:
// 仅保留具有 alpha 通道的图像
QList<QImage>images=...;
QFuture<void>alphaImages=QtConcurrent::filter(images,&QImage::hasAlphaChannel);
// 获取灰度图像
QList<QImage>images=...;
QFuture<QImage>灰度图像=QtConcurrent::filtered(images,&QImage::isGrayscale);
// 创建包含所有可打印字符的集合
QList<QChar>characters=...;
QFuture<QSet<QChar>>set=QtConcurrent::filteredReduced(字符, qOverload<>(&QChar::isPrint),
qOverload<const QChar&>(&QSet<QChar>::insert));请注意qOverload 的用法。这是为了消除方法的歧义,因为这些方法有多个重载。
另请注意,在使用 QtConcurrent::filteredReduced() 时,可以自由混合使用普通函数和成员函数:
// 可以在 QtConcurrent::filteredReduced() 中混合使用普通函数和成员函数
// 创建一个包含所有小写字符串的字典
extern boolallLowerCase(constQString&string);
QStringList strings=...;
QFuture<QSet<QString>>lowerCase=QtConcurrent::filteredReduced(strings,allLowerCase,
qOverload<const QString&>(&QSet<QString>::insert));
// 创建由所有灰度图像组成的拼贴画
extern voidaddToCollage(QImage &collage, const QImage &grayscaleImage);
QList<QImage>images=...;
QFuture<QImage>拼贴=QtConcurrent::filteredReduced(images,&QImage::isGrayscale,addToCollage);使用函数对象
QtConcurrent::filter()、QtConcurrent::filtered() 和 QtConcurrent::filteredReduced() 接受函数对象作为过滤函数。这些函数对象可用于为函数调用添加状态:
struct StartsWith
{
StartsWith(const QString &string)
: m_string(string) { }
bool operator()(const QString &testString)
{
return testString.startsWith(m_string);
}
QString m_string;
};
QList<QString> strings = ...;
QFuture<QString> fooString = QtConcurrent::filtered(strings, StartsWith(QLatin1String("Foo")));“reduce” 函数同样支持函数对象:
struct StringTransform
{
void operator()(QString &result, const QString &value);
};
QFuture<QString> fooString =
QtConcurrent::filteredReduced(strings, StartsWith(QLatin1String("Foo")), StringTransform());使用 Lambda 表达式
QtConcurrent::filter()、QtConcurrent::filtered() 和 QtConcurrent::filteredReduced() 接受用于过滤和归约函数的 lambda 表达式:
// keep only even integers
QList<int> list { 1, 2, 3, 4 };
QtConcurrent::blockingFilter(list, [](int n) { return (n & 1) == 0; });
// retrieve only even integers
QList<int> list2 { 1, 2, 3, 4 };
QFuture<int> future = QtConcurrent::filtered(list2, [](int x) {
return (x & 1) == 0;
});
QList<int> results = future.results();
// add up all even integers
QList<int> list3 { 1, 2, 3, 4 };
QFuture<int> sum = QtConcurrent::filteredReduced(list3,
[](int x) {
return (x & 1) == 0;
},
[](int &sum, int x) {
sum += x;
}
);在使用 QtConcurrent::filteredReduced() 或 QtConcurrent::blockingFilteredReduced() 时,您可以自由地混合使用普通函数、成员函数和 lambda 表达式。
void intSumReduce(int &sum, int x)
{
sum += x;
}
QList<int> list { 1, 2, 3, 4 };
QFuture<int> sum = QtConcurrent::filteredReduced(list,
[] (int x) {
return (x & 1) == 0;
},
intSumReduce
);您还可以将一个 lambda 表达式作为 reduce 对象传递:
bool keepEvenIntegers(int x)
{
return (x & 1) == 0;
}
QList<int> list { 1, 2, 3, 4 };
QFuture<int> sum = QtConcurrent::filteredReduced(list,
keepEvenIntegers,
[](int &sum, int x) {
sum += x;
}
);包装接受多个参数的函数
若要使用一个接受多个参数的过滤函数,可以使用 lambda 函数或 `std::bind() ` 将其转换为一个接受单个参数的函数。
例如,我们使用 `QString::contains()`:
bool QString::contains(const QRegularExpression ®exp) const;QString::contains() 接受 2 个参数(包括“this”指针),无法直接与 QtConcurrent::filtered() 配合使用,因为 QtConcurrent::filtered() 期望接收一个只接受一个参数的函数。 若要将QString::contains() 与 QtConcurrent::filtered() 结合使用,我们必须为regexp参数提供一个值:
QStringList strings = ...;
QFuture<QString> future = QtConcurrent::filtered(list, [](const QString &str) {
return str.contains(QRegularExpression("^\\S+$")); // matches strings without whitespace
});© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.