Apache Lucene is a high-performance, full-featured search engine library. It supports structured search, full-text search, faceting, nearest-neighbor search across high-dimensionality vectors, spell correction or query suggestions. Here's a simple example how to use Lucene for indexing and searching (using JUnit to check if the results are what we expect):

    Analyzer analyzer = new StandardAnalyzer();

    Path indexPath = Files.createTempDirectory("tempIndex");
    try (Directory directory = FSDirectory.open(indexPath)) {
      IndexWriterConfig config = new IndexWriterConfig(analyzer);
      try (IndexWriter iwriter = new IndexWriter(directory, config)) {
        Document doc = new Document();
        String text = "This is the text to be indexed.";
        doc.add(new Field("fieldname", text, TextField.TYPE_STORED));
        iwriter.addDocument(doc);
      }

      // Now search the index:
      try (DirectoryReader ireader = DirectoryReader.open(directory)) {
        IndexSearcher isearcher = new IndexSearcher(ireader);
        // Parse a simple query that searches for "text":
        QueryParser parser = new QueryParser("fieldname", analyzer);
        Query query = parser.parse("text");
        ScoreDoc[] hits = isearcher.search(query, 10).scoreDocs;
        assertEquals(1, hits.length);
        // Iterate through the results:
        StoredFields storedFields = isearcher.storedFields();
        for (int i = 0; i < hits.length; i++) {
          Document hitDoc = storedFields.document(hits[i].doc);
          assertEquals("This is the text to be indexed.", hitDoc.get("fieldname"));
        }
      }
    } finally {
      IOUtils.rm(indexPath);
    }

The Lucene API is divided into several packages:

To use Lucene, an application should:
  1. Create {@link org.apache.lucene.document.Document Document}s by adding {@link org.apache.lucene.document.Field Field}s;
  2. Create an {@link org.apache.lucene.index.IndexWriter IndexWriter} and add documents to it with {@link org.apache.lucene.index.IndexWriter#addDocument(Iterable) addDocument()};
  3. Call QueryParser.parse() to build a query from a string; and
  4. Create an {@link org.apache.lucene.search.IndexSearcher IndexSearcher} and pass the query to its {@link org.apache.lucene.search.IndexSearcher#search(org.apache.lucene.search.Query, int) search()} method.
Some simple examples of code which does this are: To demonstrate these, try something like:
> java -cp lucene-core.jar:lucene-demo.jar:lucene-analysis-common.jar org.apache.lucene.demo.IndexFiles -index index -docs rec.food.recipes/soups
adding rec.food.recipes/soups/abalone-chowder
  [ ... ]

> java -cp lucene-core.jar:lucene-demo.jar:lucene-queryparser.jar:lucene-analysis-common.jar org.apache.lucene.demo.SearchFiles
Query: chowder
Searching for: chowder
34 total matching documents
1. rec.food.recipes/soups/spam-chowder
  [ ... thirty-four documents contain the word "chowder" ... ]

Query: "clam chowder" AND Manhattan
Searching for: +"clam chowder" +manhattan
2 total matching documents
1. rec.food.recipes/soups/clam-chowder
  [ ... two documents contain the phrase "clam chowder" and the word "manhattan" ... ]
    [ Note: "+" and "-" are canonical, but "AND", "OR" and "NOT" may be used. ]