并发过滤和过滤-减少
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
并发过滤
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::filteredReduced() 与 QtConcurrent::filtered() 类似,但不同之处在于它使用减少函数将结果组合成一个单独的值。
减少函数必须具有以下形式
V function(T &result, const U &intermediate)
T 是最终结果类型,U 是过滤项的类型。请注意,减少函数的返回值和返回类型不使用。
这样调用 QtConcurrent::filteredReduced()
void addToDictionary(QSet<QString> &dictionary, const QString &string) { dictionary.insert(string); } QStringList strings = ...; QFuture<QSet<QString>> dictionary = QtConcurrent::filteredReduced(strings, allLowerCase, addToDictionary);
减少函数将在过滤器函数保留的每个结果上调用一次,并且应该将 中间 结果合并到 结果 变量中。QtConcurrent::filteredReduced() 保证一次只有一个线程调用减少,因此不需要使用互斥锁锁定结果变量。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() 接受成员函数的指针。成员函数的类类型必须与序列中存储的类型匹配
// keep only images with an alpha channel QList<QImage> images = ...; QFuture<void> alphaImages = QtConcurrent::filter(images, &QImage::hasAlphaChannel); // retrieve gray scale images QList<QImage> images = ...; QFuture<QImage> grayscaleImages = QtConcurrent::filtered(images, &QImage::isGrayscale); // create a set of all printable characters QList<QChar> characters = ...; QFuture<QSet<QChar>> set = QtConcurrent::filteredReduced(characters, qOverload<>(&QChar::isPrint), qOverload<const QChar&>(&QSet<QChar>::insert));
请注意 qOverload 的使用。它用于解决具有多个重载的方法的歧义
此外,请注意,在调用 QtConcurrent::filteredReduced() 时,可以自由混合使用普通函数和成员函数
// can mix normal functions and member functions with QtConcurrent::filteredReduced() // create a dictionary of all lower cased strings extern bool allLowerCase(const QString &string); QStringList strings = ...; QFuture<QSet<QString>> lowerCase = QtConcurrent::filteredReduced(strings, allLowerCase, qOverload<const QString&>(&QSet<QString>::insert)); // create a collage of all gray scale images 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() 接受过滤函数的函数对象。这些函数对象可以用来自定义函数调用中的状态
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")));
还支持对汇总函数使用函数对象
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 作为汇总对象传递
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 });
© 2024 Qt 公司有限。本说明书中包含的文档贡献是各自所有者的版权。所提供的文档是根据免费软件基金会发布的 GNU 自由文档许可证版本 1.3 的条款许可的。Qt 和相应的标志是芬兰的 Qt 公司及其在全球的子公司和关联公司的 商标。所有其他商标均为其各自所有者的财产。