diff --git a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaOptionalAsSet.java b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaOptionalAsSet.java
new file mode 100644
index 0000000000..6390609d0f
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaOptionalAsSet.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2025 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openrewrite.java.migrate.guava;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Preconditions;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaTemplate;
+import org.openrewrite.java.JavaVisitor;
+import org.openrewrite.java.MethodMatcher;
+import org.openrewrite.java.search.UsesMethod;
+import org.openrewrite.java.tree.J;
+
+import java.util.Set;
+
+import static java.util.Collections.singleton;
+
+public class NoGuavaOptionalAsSet extends Recipe {
+ private static final MethodMatcher OPTIONAL_AS_SET = new MethodMatcher("com.google.common.base.Optional asSet()");
+
+ @Override
+ public String getDisplayName() {
+ return "Prefer `Optional.stream().collect(Collectors.toSet())`";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Prefer `Optional.stream().collect(Collectors.toSet())` over `Optional.asSet()`.";
+ }
+
+ @Override
+ public Set getTags() {
+ return singleton("guava");
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return Preconditions.check(new UsesMethod<>(OPTIONAL_AS_SET), new JavaVisitor() {
+ @Override
+ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
+ if (OPTIONAL_AS_SET.matches(method)) {
+ maybeAddImport("java.util.stream.Collectors");
+ return JavaTemplate.builder("#{any(java.util.Optional)}.stream().collect(Collectors.toSet())")
+ .imports("java.util.stream.Collectors")
+ .build()
+ .apply(getCursor(),
+ method.getCoordinates().replace(),
+ method.getSelect());
+ }
+ return super.visitMethodInvocation(method, ctx);
+ }
+ }
+ );
+ }
+}
diff --git a/src/main/resources/META-INF/rewrite/no-guava.yml b/src/main/resources/META-INF/rewrite/no-guava.yml
index 59ed8c81a9..be80aa2b63 100644
--- a/src/main/resources/META-INF/rewrite/no-guava.yml
+++ b/src/main/resources/META-INF/rewrite/no-guava.yml
@@ -153,6 +153,7 @@ recipeList:
- org.openrewrite.java.migrate.guava.PreferJavaUtilOptionalOrElseNull
- org.openrewrite.java.migrate.guava.NoGuavaOptionalFromJavaUtil
- org.openrewrite.java.migrate.guava.NoGuavaOptionalToJavaUtil
+ - org.openrewrite.java.migrate.guava.NoGuavaOptionalAsSet
- org.openrewrite.java.ChangeMethodName:
methodPattern: com.google.common.base.Optional absent()
newMethodName: empty
diff --git a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilOptionalTest.java b/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilOptionalTest.java
index be211fc419..c4b3809426 100644
--- a/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilOptionalTest.java
+++ b/src/test/java/org/openrewrite/java/migrate/guava/PreferJavaUtilOptionalTest.java
@@ -324,13 +324,14 @@ String foo(Optional optional) {
);
}
- @ExpectedToFail("Not yet implemented")
@Test
void asSetToStreamCollectToSet() {
// Comparison to java.util.Optional: this method has no equivalent in Java 8's Optional class. However, some use cases can be written with calls to optional.stream().
//language=java
rewriteRun(java(
"""
+ import java.util.Set;
+
import com.google.common.base.Optional;
class A {