目录
4.3 QtConcurrent::filteredReduced
4.4 QtConcurrent::blockingFilter
4.5 QtConcurrent::blockingFiltered
4.6 QtConcurrent::blockingFilteredReduced
1、Header: #include <QtConcurrent>
2、qmake: QT += concurrent
3、详细描述
QtConcurrent::filter(), QtConcurrent::filtered()和QtConcurrent::filteredReduced()函数以一个序列(例如一个QList或一个QVector)并行地过滤项。
QtConcurrent::filter()在原地修改一个序列;
QtConcurrent::filtered()返回一个包含被过滤内容的新序列;
而QtConcurrent::filteredReduced()返回一个结果;
上面的每个函数都有一个阻塞变量,它返回最终结果results,而不是QFuture。可以与异步变体相同的方式使用它们。
QStringList strings = ...;
//每一次调用均阻塞,直到操作完成
QStringList lowerCaseStrings = QtConcurrent::blockingFiltered(strings, allLowerCase);
QtConcurrent::blockingFilter(strings, allLowerCase);
QSet<QString> dictionary = QtConcurrent::blockingFilteredReduced(strings, allLowerCase, addToDictionary);
注意,上面的结果类型不是QFuture对象,而是实际的结果类型(在本例中,QStringList和QSet<QString>)。
4、number functions
4.1 QtConcurrent::filtered
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()。
4.2 QtConcurrent::filter
QStringList strings = ...;
QFuture<void> future = QtConcurrent::filter(strings, allLowerCase);
由于序列是在适当的地方修改的,QtConcrrent::filter()不会通过QFuture返回任何结果。但是,仍然可以使用QFuture和QFutureWatcher来监视过滤器的状态。
4.3 QtConcurrent::filteredReduced
QtConcurrent::filteredReduced()类似于QtConcurrent::filtered(),但是不是返回一个带有筛选结果的序列,而是使用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);
filter函数执行都将调用reduce(),并且应该将中间值合并到结果变量中。
QtConcurrent::filteredReduced()保证每次只有一个线程会调用reduce函数,所以没有必要使用互斥锁来锁定结果变量。QtConcurrent::ReduceOptions枚举类型可以控制其顺序。
4.4 QtConcurrent::blockingFilter
void QtConcurrent::blockingFilter(Sequence &sequence, FilterFunction filterFunction)
对容器中的每个项按顺序调用filterFunction一次。如果filterFunction返回true,则该项按顺序保存;否则,将从序列中删除该项。
注意:这个函数将阻塞直到序列中的所有项都被处理完。
4.5 QtConcurrent::blockingFiltered
Sequence QtConcurrent::blockingFiltered(const Sequence &sequence, FilterFunction filterFunction)
对容器中的每个项调用filterFunction一次,并返回保留项的新序列。如果filterFunction返回true,则该项的副本将被放入新的Sequence中。否则,该项目将不会出现在新的序列中。
注意:这个函数将阻塞直到序列中的所有项都被处理完。
Sequence QtConcurrent::blockingFiltered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction)
从开始到结束对每个项调用filterFunction一次,并返回保留项的新序列。如果filterFunction返回true,则该项的副本将被放入新的Sequence中。否则,该项目将不会出现在新的序列中。
注意:这个函数将会阻塞,直到迭代器到达正在处理的序列的末尾。
4.6 QtConcurrent::blockingFilteredReduced
T QtConcurrent::blockingFilteredReduced(const Sequence &sequence, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)
对容器中每个项按顺序调用filterFunction函数一次。如果filterFunction为一个条目返回true,那么该条目将被传递给reduceFunction。换句话说,返回值是每个filterFunction返回true项的reduceFunction的结果。
注意,当filterFunction被并发调用时,每次只有一个线程会调用reduceFunction。如果reduceOptions为QtConcurrent::UnorderedReduce,那么reduceFunction的调用顺序是未定义的。如果reduceOptions为QtConcurrent::OrderedReduce,则reduceFunction将按原始顺序调用。
T QtConcurrent::blockingFilteredReduced(ConstIterator begin, ConstIterator end, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)
对容器中每个项按顺序调用filterFunction函数一次。如果filterFunction返回的时是true,那么该元素被保留并传递给reduceFunction函数。
注意,当filterFunction被并发调用的时候,每次只有一个线程会调用reduceFunction。如果reduceOptions 是QtConcurrent::UnorderedReduce,那么reduceFunction的调用顺序是未定义的。如果reduceOptions为QtConcurrent::OrderedReduce,则reduceFunction将按原始顺序调用。
5 API 附加特征
5.1 使用迭代器代替容器
上面的每个函数都有一个变量,接受迭代器范围而不是序列。你使用它们的方式与序列变体相同:
QStringList strings = ...;
QFuture<QString> lowerCaseStrings = QtConcurrent::filtered(strings.constBegin(), strings.constEnd(), allLowerCase);
// 就地筛选只适用于非const迭代器
QFuture<void> future = QtConcurrent::filter(strings.begin(), strings.end(), allLowerCase);
QFuture<QSet<QString> > dictionary = QtConcurrent::filteredReduced(strings.constBegin(), strings.constEnd(), allLowerCase, addToDictionary);
5.2 使用成员函数
QtConcurrent::filter(), QtConcurrent::filtered()和QtConcurrent::filteredReduced()接受指向成员函数的指针。成员函数类类型必须匹配存储在序列中的类型:
// 只保留带有alpha通道的图像
QList<QImage> images = ...;
QFuture<void> alphaImages = QtConcurrent::filter(images, &QImage::hasAlphaChannel);
//检索灰度图像
QList<QImage> images = ...;
QFuture<QImage> grayscaleImages = QtConcurrent::filtered(images, &QImage::isGrayscale);
// 创建一组所有可打印字符
QList<QChar> characters = ...;
QFuture<QSet<QChar> > set = QtConcurrent::filteredReduced(characters, &QChar::isPrint, &QSet<QChar>::insert);
注意,当使用QtConcurrent::filteredReduced()时,可以自由地混合使用普通函数和成员函数;
//可以使用QtConcurrent::filteredReduced()混合普通函数和成员函数
//创建一个所有小写字符串的字典
extern bool allLowerCase(const QString &string);
QStringList strings = ...;
QFuture<QSet<int> > averageWordLength = QtConcurrent::filteredReduced(strings, allLowerCase, QSet<QString>::insert);
//创建所有灰度图像的拼贴
extern void addToCollage(QImage &collage, const QImage &grayscaleImage);
QList<QImage> images = ...;
QFuture<QImage> collage = QtConcurrent::filteredReduced(images, &QImage::isGrayscale, addToCollage);
使用函数对象
QtConcurrent::filter(), QtConcurrent::filtered()和QtConcurrent::filteredReduced()接受函数对象,这些对象可以用来为函数调用添加状态。result_type typedef必须定义函数调用操作符的结果类型:
struct StartsWith
{
StartsWith(const QString &string): m_string(string) { }
typedef bool result_type;
bool operator()(const QString &testString)
{
return testString.startsWith(m_string);
}
QString m_string;
};
QFuture<QString> fooString = QtConcurrent::filtered(images, StartsWith(QLatin1String("Foo")));
5.3 使用多个参数的函数
如果您想要使用一个接受多个参数的筛选函数,您可以使用lambda函数或std::bind()将其转换为一个接受一个参数的函数。
例如,我们使用QString::contains():
bool QString::contains(const QRegularExpression ®exp) const;
QString::contains()接受2个参数(包括"this"指针),不能直接与QtConcurrent::filtered()一起使用,因为QtConcurrent::filtered()期望一个只有一个参数的函数。要在QtConcurrent::filtered()中使用QString::contains(),我们必须为regexp参数提供一个值:
QStringList strings = ...;
QFuture<QString> future = QtConcurrent::filtered(list, [](const QString &str) {
return str.contains(QRegularExpression("^\\S+$")); // matches strings without whitespace
});